diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 76b8266cae87c4b0b3fbf90e4bf72626aad7c9f3..c4727a0c267d3ecb5a3a5495945ce417d5adc38a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -115,6 +115,10 @@ clang/test/AST/Interp/ @tbaederr /mlir/**/LLVMIR/**/BasicPtxBuilderInterface* @grypp /mlir/**/NVVM*/ @grypp +# MLIR Python Bindings +/mlir/test/python/ @makslevental @stellaraccident +/mlir/python/ @makslevental @stellaraccident + # BOLT /bolt/ @aaupov @maksfb @rafaelauler @ayermolo @dcci diff --git a/.github/workflows/pr-code-format.yml b/.github/workflows/pr-code-format.yml index 10b18f245d8965a69251038f44f1505fc40c0cf0..983838858ba43ed90cca953b6b00668d6746f5df 100644 --- a/.github/workflows/pr-code-format.yml +++ b/.github/workflows/pr-code-format.yml @@ -1,4 +1,8 @@ name: "Check code formatting" + +permissions: + contents: read + on: pull_request: branches: diff --git a/bolt/docs/BAT.md b/bolt/docs/BAT.md index f23ef1abf8761cc58fc2249ef0da43ae0034e114..7ffb5d7c00816e11df469e3de6372e462d1eb616 100644 --- a/bolt/docs/BAT.md +++ b/bolt/docs/BAT.md @@ -81,9 +81,10 @@ Hot indices are delta encoded, implicitly starting at zero. | `FuncHash` | 8b | Function hash for input function | Hot | | `NumBlocks` | ULEB128 | Number of basic blocks in the original function | Hot | | `NumSecEntryPoints` | ULEB128 | Number of secondary entry points in the original function | Hot | +| `ColdInputSkew` | ULEB128 | Skew to apply to all input offsets | Cold | | `NumEntries` | ULEB128 | Number of address translation entries for a function | Both | -| `EqualElems` | ULEB128 | Number of equal offsets in the beginning of a function | Hot | -| `BranchEntries` | Bitmask, `alignTo(EqualElems, 8)` bits | If `EqualElems` is non-zero, bitmask denoting entries with `BRANCHENTRY` bit | Hot | +| `EqualElems` | ULEB128 | Number of equal offsets in the beginning of a function | Both | +| `BranchEntries` | Bitmask, `alignTo(EqualElems, 8)` bits | If `EqualElems` is non-zero, bitmask denoting entries with `BRANCHENTRY` bit | Both | Function header is followed by *Address Translation Table* with `NumEntries` total entries, and *Secondary Entry Points* table with `NumSecEntryPoints` @@ -99,8 +100,8 @@ entry is encoded. Input offsets implicitly start at zero. | `BBHash` | Optional, 8b | Basic block hash in input binary | BB | | `BBIdx` | Optional, Delta, ULEB128 | Basic block index in input binary | BB | -For hot fragments, the table omits the first `EqualElems` input offsets -where the input offset equals output offset. +The table omits the first `EqualElems` input offsets where the input offset +equals output offset. `BRANCHENTRY` bit denotes whether a given offset pair is a control flow source (branch or call instruction). If not set, it signifies a control flow target diff --git a/bolt/include/bolt/Core/BinaryData.h b/bolt/include/bolt/Core/BinaryData.h index 495163f1b61aafd2360b9699fcda4f95844f1dd3..8a67b3e73b802d2a2a620f13bb59b58c7689aa9f 100644 --- a/bolt/include/bolt/Core/BinaryData.h +++ b/bolt/include/bolt/Core/BinaryData.h @@ -107,7 +107,6 @@ public: std::vector &getSymbols() { return Symbols; } bool hasName(StringRef Name) const; - bool hasNameRegex(StringRef Name) const; bool nameStartsWith(StringRef Prefix) const; bool hasSymbol(const MCSymbol *Symbol) const { diff --git a/bolt/include/bolt/Profile/BoltAddressTranslation.h b/bolt/include/bolt/Profile/BoltAddressTranslation.h index eef05e8a0e681406cd1a48784ece7edf5f85ff4a..68b993ee363cc0d0a3bbd59113e4a42c896da4cb 100644 --- a/bolt/include/bolt/Profile/BoltAddressTranslation.h +++ b/bolt/include/bolt/Profile/BoltAddressTranslation.h @@ -149,9 +149,9 @@ private: /// entries in function address translation map. APInt calculateBranchEntriesBitMask(MapTy &Map, size_t EqualElems); - /// Calculate the number of equal offsets (output = input) in the beginning - /// of the function. - size_t getNumEqualOffsets(const MapTy &Map) const; + /// Calculate the number of equal offsets (output = input - skew) in the + /// beginning of the function. + size_t getNumEqualOffsets(const MapTy &Map, uint32_t Skew) const; std::map Maps; diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index 47eae964e816c5565697bdc2ef974bdfecdff4dc..ad2eb18caf109b0c987b1e568404649142599c9c 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -555,6 +555,9 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address, const uint64_t NextJTAddress, JumpTable::AddressesType *EntriesAsAddress, bool *HasEntryInFragment) const { + // Target address of __builtin_unreachable. + const uint64_t UnreachableAddress = BF.getAddress() + BF.getSize(); + // Is one of the targets __builtin_unreachable? bool HasUnreachable = false; @@ -564,9 +567,15 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address, // Number of targets other than __builtin_unreachable. uint64_t NumRealEntries = 0; - auto addEntryAddress = [&](uint64_t EntryAddress) { - if (EntriesAsAddress) - EntriesAsAddress->emplace_back(EntryAddress); + // Size of the jump table without trailing __builtin_unreachable entries. + size_t TrimmedSize = 0; + + auto addEntryAddress = [&](uint64_t EntryAddress, bool Unreachable = false) { + if (!EntriesAsAddress) + return; + EntriesAsAddress->emplace_back(EntryAddress); + if (!Unreachable) + TrimmedSize = EntriesAsAddress->size(); }; ErrorOr Section = getSectionForAddress(Address); @@ -618,8 +627,8 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address, : *getPointerAtAddress(EntryAddress); // __builtin_unreachable() case. - if (Value == BF.getAddress() + BF.getSize()) { - addEntryAddress(Value); + if (Value == UnreachableAddress) { + addEntryAddress(Value, /*Unreachable*/ true); HasUnreachable = true; LLVM_DEBUG(dbgs() << formatv("OK: {0:x} __builtin_unreachable\n", Value)); continue; @@ -673,6 +682,13 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address, addEntryAddress(Value); } + // Trim direct/normal jump table to exclude trailing unreachable entries that + // can collide with a function address. + if (Type == JumpTable::JTT_NORMAL && EntriesAsAddress && + TrimmedSize != EntriesAsAddress->size() && + getBinaryFunctionAtAddress(UnreachableAddress)) + EntriesAsAddress->resize(TrimmedSize); + // It's a jump table if the number of real entries is more than 1, or there's // one real entry and one or more special targets. If there are only multiple // special targets, then it's not a jump table. @@ -1864,7 +1880,7 @@ MarkerSymType BinaryContext::getMarkerType(const SymbolRef &Symbol) const { // For aarch64 and riscv, the ABI defines mapping symbols so we identify data // in the code section (see IHI0056B). $x identifies a symbol starting code or // the end of a data chunk inside code, $d identifies start of data. - if ((!isAArch64() && !isRISCV()) || ELFSymbolRef(Symbol).getSize()) + if (isX86() || ELFSymbolRef(Symbol).getSize()) return MarkerSymType::NONE; Expected NameOrError = Symbol.getName(); diff --git a/bolt/lib/Core/BinaryData.cpp b/bolt/lib/Core/BinaryData.cpp index 0068a935800429f6b9f4cf0c56cef813f0af0486..e9ddf08d8695f468907a34db47610ea2cd9865de 100644 --- a/bolt/lib/Core/BinaryData.cpp +++ b/bolt/lib/Core/BinaryData.cpp @@ -55,14 +55,6 @@ bool BinaryData::hasName(StringRef Name) const { return false; } -bool BinaryData::hasNameRegex(StringRef NameRegex) const { - Regex MatchName(NameRegex); - for (const MCSymbol *Symbol : Symbols) - if (MatchName.match(Symbol->getName())) - return true; - return false; -} - bool BinaryData::nameStartsWith(StringRef Prefix) const { for (const MCSymbol *Symbol : Symbols) if (Symbol->getName().starts_with(Prefix)) diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp index 97d19b75200f51d0a4f6ea928e75cb2e8c70d222..6f86ddc774544a6e7a65d098b0c22e2962cbf2fd 100644 --- a/bolt/lib/Core/BinaryEmitter.cpp +++ b/bolt/lib/Core/BinaryEmitter.cpp @@ -512,7 +512,7 @@ void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, FunctionFragment &FF, // Emit sized NOPs via MCAsmBackend::writeNopData() interface on x86. // This is a workaround for invalid NOPs handling by asm/disasm layer. - if (BC.MIB->isNoop(Instr) && BC.isX86()) { + if (BC.isX86() && BC.MIB->isNoop(Instr)) { if (std::optional Size = BC.MIB->getSize(Instr)) { SmallString<15> Code; raw_svector_ostream VecOS(Code); diff --git a/bolt/lib/Core/Relocation.cpp b/bolt/lib/Core/Relocation.cpp index d16b7a94787c65d1e9b25324f3b1961b6b109102..4e888a5b147aca41eb24a0b2237e21f80c38c0a6 100644 --- a/bolt/lib/Core/Relocation.cpp +++ b/bolt/lib/Core/Relocation.cpp @@ -1064,21 +1064,19 @@ MCBinaryExpr::Opcode Relocation::getComposeOpcodeFor(uint64_t Type) { } } -#define ELF_RELOC(name, value) #name, - void Relocation::print(raw_ostream &OS) const { - static const char *X86RelocNames[] = { -#include "llvm/BinaryFormat/ELFRelocs/x86_64.def" - }; - static const char *AArch64RelocNames[] = { -#include "llvm/BinaryFormat/ELFRelocs/AArch64.def" - }; switch (Arch) { default: OS << "RType:" << Twine::utohexstr(Type); break; case Triple::aarch64: + static const char *const AArch64RelocNames[] = { +#define ELF_RELOC(name, value) #name, +#include "llvm/BinaryFormat/ELFRelocs/AArch64.def" +#undef ELF_RELOC + }; + assert(Type < ArrayRef(AArch64RelocNames).size()); OS << AArch64RelocNames[Type]; break; @@ -1088,16 +1086,22 @@ void Relocation::print(raw_ostream &OS) const { switch (Type) { default: llvm_unreachable("illegal RISC-V relocation"); -#undef ELF_RELOC #define ELF_RELOC(name, value) \ case value: \ OS << #name; \ break; #include "llvm/BinaryFormat/ELFRelocs/RISCV.def" +#undef ELF_RELOC } break; case Triple::x86_64: + static const char *const X86RelocNames[] = { +#define ELF_RELOC(name, value) #name, +#include "llvm/BinaryFormat/ELFRelocs/x86_64.def" +#undef ELF_RELOC + }; + assert(Type < ArrayRef(X86RelocNames).size()); OS << X86RelocNames[Type]; break; } diff --git a/bolt/lib/Profile/BoltAddressTranslation.cpp b/bolt/lib/Profile/BoltAddressTranslation.cpp index 0141ce189acda584e98cf73168a70c32e661cd43..7cfb9c132c2c68f98c59df0ada96c7820ef7eb94 100644 --- a/bolt/lib/Profile/BoltAddressTranslation.cpp +++ b/bolt/lib/Profile/BoltAddressTranslation.cpp @@ -153,12 +153,13 @@ APInt BoltAddressTranslation::calculateBranchEntriesBitMask(MapTy &Map, return BitMask; } -size_t BoltAddressTranslation::getNumEqualOffsets(const MapTy &Map) const { +size_t BoltAddressTranslation::getNumEqualOffsets(const MapTy &Map, + uint32_t Skew) const { size_t EqualOffsets = 0; for (const std::pair &KeyVal : Map) { const uint32_t OutputOffset = KeyVal.first; const uint32_t InputOffset = KeyVal.second >> 1; - if (OutputOffset == InputOffset) + if (OutputOffset == InputOffset - Skew) ++EqualOffsets; else break; @@ -196,12 +197,17 @@ void BoltAddressTranslation::writeMaps(std::map &Maps, SecondaryEntryPointsMap.count(Address) ? SecondaryEntryPointsMap[Address].size() : 0; + uint32_t Skew = 0; if (Cold) { auto HotEntryIt = Maps.find(ColdPartSource[Address]); assert(HotEntryIt != Maps.end()); size_t HotIndex = std::distance(Maps.begin(), HotEntryIt); encodeULEB128(HotIndex - PrevIndex, OS); PrevIndex = HotIndex; + // Skew of all input offsets for cold fragments is simply the first input + // offset. + Skew = Map.begin()->second >> 1; + encodeULEB128(Skew, OS); } else { // Function hash size_t BFHash = getBFHash(HotInputAddress); @@ -217,24 +223,21 @@ void BoltAddressTranslation::writeMaps(std::map &Maps, << '\n'); } encodeULEB128(NumEntries, OS); - // For hot fragments only: encode the number of equal offsets - // (output = input) in the beginning of the function. Only encode one offset - // in these cases. - const size_t EqualElems = Cold ? 0 : getNumEqualOffsets(Map); - if (!Cold) { - encodeULEB128(EqualElems, OS); - if (EqualElems) { - const size_t BranchEntriesBytes = alignTo(EqualElems, 8) / 8; - APInt BranchEntries = calculateBranchEntriesBitMask(Map, EqualElems); - OS.write(reinterpret_cast(BranchEntries.getRawData()), - BranchEntriesBytes); - LLVM_DEBUG({ - dbgs() << "BranchEntries: "; - SmallString<8> BitMaskStr; - BranchEntries.toString(BitMaskStr, 2, false); - dbgs() << BitMaskStr << '\n'; - }); - } + // Encode the number of equal offsets (output = input - skew) in the + // beginning of the function. Only encode one offset in these cases. + const size_t EqualElems = getNumEqualOffsets(Map, Skew); + encodeULEB128(EqualElems, OS); + if (EqualElems) { + const size_t BranchEntriesBytes = alignTo(EqualElems, 8) / 8; + APInt BranchEntries = calculateBranchEntriesBitMask(Map, EqualElems); + OS.write(reinterpret_cast(BranchEntries.getRawData()), + BranchEntriesBytes); + LLVM_DEBUG({ + dbgs() << "BranchEntries: "; + SmallString<8> BitMaskStr; + BranchEntries.toString(BitMaskStr, 2, false); + dbgs() << BitMaskStr << '\n'; + }); } const BBHashMapTy &BBHashMap = getBBHashMap(HotInputAddress); size_t Index = 0; @@ -315,10 +318,12 @@ void BoltAddressTranslation::parseMaps(std::vector &HotFuncs, uint64_t HotAddress = Cold ? 0 : Address; PrevAddress = Address; uint32_t SecondaryEntryPoints = 0; + uint64_t ColdInputSkew = 0; if (Cold) { HotIndex += DE.getULEB128(&Offset, &Err); HotAddress = HotFuncs[HotIndex]; ColdPartSource.emplace(Address, HotAddress); + ColdInputSkew = DE.getULEB128(&Offset, &Err); } else { HotFuncs.push_back(Address); // Function hash @@ -339,28 +344,25 @@ void BoltAddressTranslation::parseMaps(std::vector &HotFuncs, getULEB128Size(SecondaryEntryPoints))); } const uint32_t NumEntries = DE.getULEB128(&Offset, &Err); - // Equal offsets, hot fragments only. - size_t EqualElems = 0; + // Equal offsets. + const size_t EqualElems = DE.getULEB128(&Offset, &Err); APInt BEBitMask; - if (!Cold) { - EqualElems = DE.getULEB128(&Offset, &Err); - LLVM_DEBUG(dbgs() << formatv("Equal offsets: {0}, {1} bytes\n", - EqualElems, getULEB128Size(EqualElems))); - if (EqualElems) { - const size_t BranchEntriesBytes = alignTo(EqualElems, 8) / 8; - BEBitMask = APInt(alignTo(EqualElems, 8), 0); - LoadIntFromMemory( - BEBitMask, - reinterpret_cast( - DE.getBytes(&Offset, BranchEntriesBytes, &Err).data()), - BranchEntriesBytes); - LLVM_DEBUG({ - dbgs() << "BEBitMask: "; - SmallString<8> BitMaskStr; - BEBitMask.toString(BitMaskStr, 2, false); - dbgs() << BitMaskStr << ", " << BranchEntriesBytes << " bytes\n"; - }); - } + LLVM_DEBUG(dbgs() << formatv("Equal offsets: {0}, {1} bytes\n", EqualElems, + getULEB128Size(EqualElems))); + if (EqualElems) { + const size_t BranchEntriesBytes = alignTo(EqualElems, 8) / 8; + BEBitMask = APInt(alignTo(EqualElems, 8), 0); + LoadIntFromMemory( + BEBitMask, + reinterpret_cast( + DE.getBytes(&Offset, BranchEntriesBytes, &Err).data()), + BranchEntriesBytes); + LLVM_DEBUG({ + dbgs() << "BEBitMask: "; + SmallString<8> BitMaskStr; + BEBitMask.toString(BitMaskStr, 2, false); + dbgs() << BitMaskStr << ", " << BranchEntriesBytes << " bytes\n"; + }); } MapTy Map; @@ -375,7 +377,7 @@ void BoltAddressTranslation::parseMaps(std::vector &HotFuncs, PrevAddress = OutputAddress; int64_t InputDelta = 0; if (J < EqualElems) { - InputOffset = (OutputOffset << 1) | BEBitMask[J]; + InputOffset = ((OutputOffset + ColdInputSkew) << 1) | BEBitMask[J]; } else { InputDelta = DE.getSLEB128(&Offset, &Err); InputOffset += InputDelta; diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index eea66454b289c284de8ba3da6f4ffb4c9a6d2132..fd2477231142e3031642bce7276f56fc9ccf70ff 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -1670,7 +1670,9 @@ void RewriteInstance::disassemblePLT() { return disassemblePLTSectionAArch64(Section); if (BC->isRISCV()) return disassemblePLTSectionRISCV(Section); - return disassemblePLTSectionX86(Section, EntrySize); + if (BC->isX86()) + return disassemblePLTSectionX86(Section, EntrySize); + llvm_unreachable("Unmplemented PLT"); }; for (BinarySection &Section : BC->allocatableSections()) { @@ -2306,9 +2308,13 @@ void RewriteInstance::processRelocations() { return; for (const SectionRef &Section : InputFile->sections()) { - if (cantFail(Section.getRelocatedSection()) != InputFile->section_end() && - !BinarySection(*BC, Section).isAllocatable()) - readRelocations(Section); + section_iterator SecIter = cantFail(Section.getRelocatedSection()); + if (SecIter == InputFile->section_end()) + continue; + if (BinarySection(*BC, Section).isAllocatable()) + continue; + + readRelocations(Section); } if (NumFailedRelocations) @@ -2601,7 +2607,7 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection, const bool IsToCode = ReferencedSection && ReferencedSection->isText(); // Special handling of PC-relative relocations. - if (!IsAArch64 && !BC->isRISCV() && Relocation::isPCRelative(RType)) { + if (BC->isX86() && Relocation::isPCRelative(RType)) { if (!IsFromCode && IsToCode) { // PC-relative relocations from data to code are tricky since the // original information is typically lost after linking, even with @@ -2855,15 +2861,14 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection, BC->isRISCV()) ForceRelocation = true; - if (IsFromCode) { + if (IsFromCode) ContainingBF->addRelocation(Rel.getOffset(), ReferencedSymbol, RType, Addend, ExtractedValue); - } else if (IsToCode || ForceRelocation) { + else if (IsToCode || ForceRelocation) BC->addRelocation(Rel.getOffset(), ReferencedSymbol, RType, Addend, ExtractedValue); - } else { + else LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ignoring relocation from data to data\n"); - } } void RewriteInstance::selectFunctionsToProcess() { @@ -4300,7 +4305,7 @@ RewriteInstance::getOutputSections(ELFObjectFile *File, for (auto &SectionKV : OutputSections) { ELFShdrTy &Section = SectionKV.second; - // Ignore TLS sections as they don't take any space in the file. + // Ignore NOBITS sections as they don't take any space in the file. if (Section.sh_type == ELF::SHT_NOBITS) continue; @@ -4308,10 +4313,9 @@ RewriteInstance::getOutputSections(ELFObjectFile *File, // placed in different loadable segments. if (PrevSection && PrevSection->sh_offset + PrevSection->sh_size > Section.sh_offset) { - if (opts::Verbosity > 1) { + if (opts::Verbosity > 1) BC->outs() << "BOLT-INFO: adjusting size for section " << PrevBinSec->getOutputName() << '\n'; - } PrevSection->sh_size = Section.sh_offset - PrevSection->sh_offset; } diff --git a/bolt/test/X86/bolt-address-translation.test b/bolt/test/X86/bolt-address-translation.test index 63234b4c1d21851f447fa804669e780774a6e9c8..e6b21c14077b454e9d3e1719da8dc3c2f896b322 100644 --- a/bolt/test/X86/bolt-address-translation.test +++ b/bolt/test/X86/bolt-address-translation.test @@ -37,7 +37,7 @@ # CHECK: BOLT: 3 out of 7 functions were overwritten. # CHECK: BOLT-INFO: Wrote 6 BAT maps # CHECK: BOLT-INFO: Wrote 3 function and 58 basic block hashes -# CHECK: BOLT-INFO: BAT section size (bytes): 924 +# CHECK: BOLT-INFO: BAT section size (bytes): 928 # # usqrt mappings (hot part). We match against any key (left side containing # the bolted binary offsets) because BOLT may change where it puts instructions diff --git a/bolt/test/runtime/X86/jt-confusion.s b/bolt/test/runtime/X86/jt-confusion.s new file mode 100644 index 0000000000000000000000000000000000000000..f15c83b35b6a44e8e4733c66aad055be9fbe6a79 --- /dev/null +++ b/bolt/test/runtime/X86/jt-confusion.s @@ -0,0 +1,164 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: llvm-strip --strip-unneeded %t.o +# RUN: %clang %cflags -no-pie -nostartfiles -nostdlib -lc %t.o -o %t.exe -Wl,-q + +# RUN: llvm-bolt %t.exe -o %t.exe.bolt --relocs=1 --lite=0 + +# RUN: %t.exe.bolt + +## Check that BOLT's jump table detection diffrentiates between +## __builtin_unreachable() targets and function pointers. + +## The test case was built from the following two source files and +## modiffied for standalone build. main became _start, etc. +## $ $(CC) a.c -O1 -S -o a.s +## $ $(CC) b.c -O0 -S -o b.s + +## a.c: + +## typedef int (*fptr)(int); +## void check_fptr(fptr, int); +## +## int foo(int a) { +## check_fptr(foo, 0); +## switch (a) { +## default: +## __builtin_unreachable(); +## case 0: +## return 3; +## case 1: +## return 5; +## case 2: +## return 7; +## case 3: +## return 11; +## case 4: +## return 13; +## case 5: +## return 17; +## } +## return 0; +## } +## +## int main(int argc) { +## check_fptr(main, 1); +## return foo(argc); +## } +## +## const fptr funcs[2] = {foo, main}; + +## b.c.: + +## typedef int (*fptr)(int); +## extern const fptr funcs[2]; +## +## #define assert(C) { if (!(C)) (*(unsigned long long *)0) = 0; } +## void check_fptr(fptr f, int i) { +## assert(f == funcs[i]); +## } + + + .text + .globl foo + .type foo, @function +foo: +.LFB0: + .cfi_startproc + pushq %rbx + .cfi_def_cfa_offset 16 + .cfi_offset 3, -16 + movl %edi, %ebx + movl $0, %esi + movl $foo, %edi + call check_fptr + movl %ebx, %ebx + jmp *.L4(,%rbx,8) +.L8: + movl $5, %eax + jmp .L1 +.L7: + movl $7, %eax + jmp .L1 +.L6: + movl $11, %eax + jmp .L1 +.L5: + movl $13, %eax + jmp .L1 +.L3: + movl $17, %eax + jmp .L1 +.L10: + movl $3, %eax +.L1: + popq %rbx + .cfi_def_cfa_offset 8 + ret + .cfi_endproc +.LFE0: + .size foo, .-foo + .globl _start + .type _start, @function +_start: +.LFB1: + .cfi_startproc + pushq %rbx + .cfi_def_cfa_offset 16 + .cfi_offset 3, -16 + movl %edi, %ebx + movl $1, %esi + movl $_start, %edi + call check_fptr + movl $1, %edi + call foo + popq %rbx + .cfi_def_cfa_offset 8 + callq exit@PLT + .cfi_endproc +.LFE1: + .size _start, .-_start + .globl check_fptr + .type check_fptr, @function +check_fptr: +.LFB2: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + movq %rdi, -8(%rbp) + movl %esi, -12(%rbp) + movl -12(%rbp), %eax + cltq + movq funcs(,%rax,8), %rax + cmpq %rax, -8(%rbp) + je .L33 + movl $0, %eax + movq $0, (%rax) +.L33: + nop + popq %rbp + .cfi_def_cfa 7, 8 + ret + .cfi_endproc + + .section .rodata + .align 8 + .align 4 +.L4: + .quad .L10 + .quad .L8 + .quad .L7 + .quad .L6 + .quad .L5 + .quad .L3 + + .globl funcs + .type funcs, @object + .size funcs, 16 +funcs: + .quad foo + .quad _start diff --git a/clang-tools-extra/clang-tidy/linuxkernel/MustCheckErrsCheck.h b/clang-tools-extra/clang-tidy/linuxkernel/MustCheckErrsCheck.h index f08fed47983924d0f8cbb98e1a8789892d3b7ceb..7406aaead836e0c47e3b98b7d96eba3416e0a768 100644 --- a/clang-tools-extra/clang-tidy/linuxkernel/MustCheckErrsCheck.h +++ b/clang-tools-extra/clang-tidy/linuxkernel/MustCheckErrsCheck.h @@ -17,15 +17,8 @@ namespace clang::tidy::linuxkernel { /// linux/err.h. Also checks to see if code uses the results from functions that /// directly return a value from one of these error functions. /// -/// This is important in the Linux kernel because ERR_PTR, PTR_ERR, IS_ERR, -/// IS_ERR_OR_NULL, ERR_CAST, and PTR_ERR_OR_ZERO return values must be checked, -/// since positive pointers and negative error codes are being used in the same -/// context. These functions are marked with -/// __attribute__((warn_unused_result)), but some kernel versions do not have -/// this warning enabled for clang. -/// /// For the user-facing documentation see: -/// http://clang.llvm.org/extra/clang-tidy/checks/linuxkernel/must-use-errs.html +/// http://clang.llvm.org/extra/clang-tidy/checks/linuxkernel/must-check-errs.html class MustCheckErrsCheck : public ClangTidyCheck { public: MustCheckErrsCheck(StringRef Name, ClangTidyContext *Context) diff --git a/clang-tools-extra/clang-tidy/modernize/UseStdNumbersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseStdNumbersCheck.cpp index b299afd540b9a3cf4a71babcc04e8077988ef235..1548fc454cfb3765eb1aaf30ffa5afc8d7001fe5 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseStdNumbersCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseStdNumbersCheck.cpp @@ -29,6 +29,7 @@ #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MathExtras.h" #include +#include #include #include #include diff --git a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp index ad8048e2a92b7e37241c37836e59da568a264a86..962a243ce94d48bfcf3e9ed1ffa3278749cbb35a 100644 --- a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp @@ -169,14 +169,14 @@ public: return; if (SM.isWrittenInCommandLineFile(MacroNameTok.getLocation())) return; - Check->checkMacro(SM, MacroNameTok, Info); + Check->checkMacro(MacroNameTok, Info, SM); } /// MacroExpands calls expandMacro for macros in the main file void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, SourceRange /*Range*/, const MacroArgs * /*Args*/) override { - Check->expandMacro(MacroNameTok, MD.getMacroInfo()); + Check->expandMacro(MacroNameTok, MD.getMacroInfo(), SM); } private: @@ -187,7 +187,7 @@ private: class RenamerClangTidyVisitor : public RecursiveASTVisitor { public: - RenamerClangTidyVisitor(RenamerClangTidyCheck *Check, const SourceManager *SM, + RenamerClangTidyVisitor(RenamerClangTidyCheck *Check, const SourceManager &SM, bool AggressiveDependentMemberLookup) : Check(Check), SM(SM), AggressiveDependentMemberLookup(AggressiveDependentMemberLookup) {} @@ -258,7 +258,7 @@ public: // Fix overridden methods if (const auto *Method = dyn_cast(Decl)) { if (const CXXMethodDecl *Overridden = getOverrideMethod(Method)) { - Check->addUsage(Overridden, Method->getLocation()); + Check->addUsage(Overridden, Method->getLocation(), SM); return true; // Don't try to add the actual decl as a Failure. } } @@ -268,7 +268,7 @@ public: if (isa(Decl)) return true; - Check->checkNamedDecl(Decl, *SM); + Check->checkNamedDecl(Decl, SM); return true; } @@ -385,7 +385,7 @@ public: private: RenamerClangTidyCheck *Check; - const SourceManager *SM; + const SourceManager &SM; const bool AggressiveDependentMemberLookup; }; @@ -415,7 +415,7 @@ void RenamerClangTidyCheck::registerPPCallbacks( void RenamerClangTidyCheck::addUsage( const RenamerClangTidyCheck::NamingCheckId &Decl, SourceRange Range, - const SourceManager *SourceMgr) { + const SourceManager &SourceMgr) { // Do nothing if the provided range is invalid. if (Range.isInvalid()) return; @@ -425,8 +425,7 @@ void RenamerClangTidyCheck::addUsage( // spelling location to different source locations, and we only want to fix // the token once, before it is expanded by the macro. SourceLocation FixLocation = Range.getBegin(); - if (SourceMgr) - FixLocation = SourceMgr->getSpellingLoc(FixLocation); + FixLocation = SourceMgr.getSpellingLoc(FixLocation); if (FixLocation.isInvalid()) return; @@ -440,15 +439,15 @@ void RenamerClangTidyCheck::addUsage( if (!Failure.shouldFix()) return; - if (SourceMgr && SourceMgr->isWrittenInScratchSpace(FixLocation)) + if (SourceMgr.isWrittenInScratchSpace(FixLocation)) Failure.FixStatus = RenamerClangTidyCheck::ShouldFixStatus::InsideMacro; - if (!utils::rangeCanBeFixed(Range, SourceMgr)) + if (!utils::rangeCanBeFixed(Range, &SourceMgr)) Failure.FixStatus = RenamerClangTidyCheck::ShouldFixStatus::InsideMacro; } void RenamerClangTidyCheck::addUsage(const NamedDecl *Decl, SourceRange Range, - const SourceManager *SourceMgr) { + const SourceManager &SourceMgr) { // Don't keep track for non-identifier names. auto *II = Decl->getIdentifier(); if (!II) @@ -489,18 +488,24 @@ void RenamerClangTidyCheck::checkNamedDecl(const NamedDecl *Decl, } Failure.Info = std::move(Info); - addUsage(Decl, Range, &SourceMgr); + addUsage(Decl, Range, SourceMgr); } void RenamerClangTidyCheck::check(const MatchFinder::MatchResult &Result) { - RenamerClangTidyVisitor Visitor(this, Result.SourceManager, + if (!Result.SourceManager) { + // In principle SourceManager is not null but going only by the definition + // of MatchResult it must be handled. Cannot rename anything without a + // SourceManager. + return; + } + RenamerClangTidyVisitor Visitor(this, *Result.SourceManager, AggressiveDependentMemberLookup); Visitor.TraverseAST(*Result.Context); } -void RenamerClangTidyCheck::checkMacro(const SourceManager &SourceMgr, - const Token &MacroNameTok, - const MacroInfo *MI) { +void RenamerClangTidyCheck::checkMacro(const Token &MacroNameTok, + const MacroInfo *MI, + const SourceManager &SourceMgr) { std::optional MaybeFailure = getMacroFailureInfo(MacroNameTok, SourceMgr); if (!MaybeFailure) @@ -515,11 +520,12 @@ void RenamerClangTidyCheck::checkMacro(const SourceManager &SourceMgr, Failure.FixStatus = ShouldFixStatus::FixInvalidIdentifier; Failure.Info = std::move(Info); - addUsage(ID, Range); + addUsage(ID, Range, SourceMgr); } void RenamerClangTidyCheck::expandMacro(const Token &MacroNameTok, - const MacroInfo *MI) { + const MacroInfo *MI, + const SourceManager &SourceMgr) { StringRef Name = MacroNameTok.getIdentifierInfo()->getName(); NamingCheckId ID(MI->getDefinitionLoc(), Name); @@ -528,7 +534,7 @@ void RenamerClangTidyCheck::expandMacro(const Token &MacroNameTok, return; SourceRange Range(MacroNameTok.getLocation(), MacroNameTok.getEndLoc()); - addUsage(ID, Range); + addUsage(ID, Range, SourceMgr); } static std::string diff --git a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.h b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.h index 38228fb59bf62487674a5ba28bbe8449956d37e2..be5b6f0c7f76785d7f2aada7dd394cf3a568ddd4 100644 --- a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.h +++ b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.h @@ -108,18 +108,19 @@ public: llvm::DenseMap; /// Check Macros for style violations. - void checkMacro(const SourceManager &SourceMgr, const Token &MacroNameTok, - const MacroInfo *MI); + void checkMacro(const Token &MacroNameTok, const MacroInfo *MI, + const SourceManager &SourceMgr); /// Add a usage of a macro if it already has a violation. - void expandMacro(const Token &MacroNameTok, const MacroInfo *MI); + void expandMacro(const Token &MacroNameTok, const MacroInfo *MI, + const SourceManager &SourceMgr); void addUsage(const RenamerClangTidyCheck::NamingCheckId &Decl, - SourceRange Range, const SourceManager *SourceMgr = nullptr); + SourceRange Range, const SourceManager &SourceMgr); /// Convenience method when the usage to be added is a NamedDecl. void addUsage(const NamedDecl *Decl, SourceRange Range, - const SourceManager *SourceMgr = nullptr); + const SourceManager &SourceMgr); void checkNamedDecl(const NamedDecl *Decl, const SourceManager &SourceMgr); diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 9e321dce4c5041901ef21708b2366f2722514b7a..89eee392837af4955a584fca6c0515949924baa1 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -89,7 +89,11 @@ const CodeCompleteOptions::CodeCompletionRankingModel namespace { -CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) { +// Note: changes to this function should also be reflected in the +// CodeCompletionResult overload where appropriate. +CompletionItemKind +toCompletionItemKind(index::SymbolKind Kind, + const llvm::StringRef *Signature = nullptr) { using SK = index::SymbolKind; switch (Kind) { case SK::Unknown: @@ -99,7 +103,10 @@ CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) { case SK::NamespaceAlias: return CompletionItemKind::Module; case SK::Macro: - return CompletionItemKind::Text; + // Use macro signature (if provided) to tell apart function-like and + // object-like macros. + return Signature && Signature->contains('(') ? CompletionItemKind::Function + : CompletionItemKind::Constant; case SK::Enum: return CompletionItemKind::Enum; case SK::Struct: @@ -150,6 +157,8 @@ CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) { llvm_unreachable("Unhandled clang::index::SymbolKind."); } +// Note: changes to this function should also be reflected in the +// index::SymbolKind overload where appropriate. CompletionItemKind toCompletionItemKind(const CodeCompletionResult &Res, CodeCompletionContext::Kind CtxKind) { if (Res.Declaration) @@ -379,7 +388,8 @@ struct CodeCompletionBuilder { if (Completion.Scope.empty()) Completion.Scope = std::string(C.IndexResult->Scope); if (Completion.Kind == CompletionItemKind::Missing) - Completion.Kind = toCompletionItemKind(C.IndexResult->SymInfo.Kind); + Completion.Kind = toCompletionItemKind(C.IndexResult->SymInfo.Kind, + &C.IndexResult->Signature); if (Completion.Name.empty()) Completion.Name = std::string(C.IndexResult->Name); if (Completion.FilterText.empty()) diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp index 85b8fc549b016e4dc159ddf591266dba80511fbb..5c4e2150cf3123bb11ecb567887ee269ec6f0ca7 100644 --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -409,7 +409,7 @@ private: // Framework headers are spelled as , not // "path/FrameworkName.framework/Headers/Foo.h". auto &HS = PP->getHeaderSearchInfo(); - if (const auto *HFI = HS.getExistingFileInfo(*FE, /*WantExternal*/ false)) + if (const auto *HFI = HS.getExistingFileInfo(*FE)) if (!HFI->Framework.empty()) if (auto Spelling = getFrameworkHeaderIncludeSpelling(*FE, HFI->Framework, HS)) diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 49337bddf98d5d93c22f75169844bc08ded35426..8fbac73cb653bcc20d4b68a92a6e80f2bd881315 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -671,7 +671,8 @@ TEST(CompletionTest, Kinds) { #define MACRO 10 int X = ^ )cpp", - {func("indexFunction"), var("indexVariable"), cls("indexClass")}); + {func("indexFunction"), var("indexVariable"), cls("indexClass"), + macro("indexObjMacro"), macro("indexFuncMacro", "(x, y)")}); EXPECT_THAT(Results.Completions, AllOf(has("function", CompletionItemKind::Function), has("variable", CompletionItemKind::Variable), @@ -680,7 +681,9 @@ TEST(CompletionTest, Kinds) { has("MACRO", CompletionItemKind::Constant), has("indexFunction", CompletionItemKind::Function), has("indexVariable", CompletionItemKind::Variable), - has("indexClass", CompletionItemKind::Class))); + has("indexClass", CompletionItemKind::Class), + has("indexObjMacro", CompletionItemKind::Constant), + has("indexFuncMacro", CompletionItemKind::Function))); Results = completions("nam^"); EXPECT_THAT(Results.Completions, diff --git a/clang-tools-extra/clangd/unittests/TestIndex.cpp b/clang-tools-extra/clangd/unittests/TestIndex.cpp index 278336bdde2ee5cd2f50a36eb8ffb892490f44c0..b13a5d32d175245b64a830189afc0d843d51ac68 100644 --- a/clang-tools-extra/clangd/unittests/TestIndex.cpp +++ b/clang-tools-extra/clangd/unittests/TestIndex.cpp @@ -38,7 +38,7 @@ static std::string replace(llvm::StringRef Haystack, llvm::StringRef Needle, // Helpers to produce fake index symbols for memIndex() or completions(). // USRFormat is a regex replacement string for the unqualified part of the USR. Symbol sym(llvm::StringRef QName, index::SymbolKind Kind, - llvm::StringRef USRFormat) { + llvm::StringRef USRFormat, llvm::StringRef Signature) { Symbol Sym; std::string USR = "c:"; // We synthesize a few simple cases of USRs by hand! size_t Pos = QName.rfind("::"); @@ -55,6 +55,7 @@ Symbol sym(llvm::StringRef QName, index::SymbolKind Kind, Sym.SymInfo.Kind = Kind; Sym.Flags |= Symbol::IndexedForCodeCompletion; Sym.Origin = SymbolOrigin::Static; + Sym.Signature = Signature; return Sym; } @@ -86,6 +87,10 @@ Symbol conceptSym(llvm::StringRef Name) { return sym(Name, index::SymbolKind::Concept, "@CT@\\0"); } +Symbol macro(llvm::StringRef Name, llvm::StringRef ArgList) { + return sym(Name, index::SymbolKind::Macro, "@macro@\\0", ArgList); +} + Symbol objcSym(llvm::StringRef Name, index::SymbolKind Kind, llvm::StringRef USRPrefix) { Symbol Sym; diff --git a/clang-tools-extra/clangd/unittests/TestIndex.h b/clang-tools-extra/clangd/unittests/TestIndex.h index 9280b0b12a67fe7a9f57e4e2344f32d84febc953..0699b29392d720dfad46335e823b837724f36316 100644 --- a/clang-tools-extra/clangd/unittests/TestIndex.h +++ b/clang-tools-extra/clangd/unittests/TestIndex.h @@ -20,7 +20,7 @@ Symbol symbol(llvm::StringRef QName); // Helpers to produce fake index symbols with proper SymbolID. // USRFormat is a regex replacement string for the unqualified part of the USR. Symbol sym(llvm::StringRef QName, index::SymbolKind Kind, - llvm::StringRef USRFormat); + llvm::StringRef USRFormat, llvm::StringRef Signature = {}); // Creats a function symbol assuming no function arg. Symbol func(llvm::StringRef Name); // Creates a class symbol. @@ -35,6 +35,8 @@ Symbol var(llvm::StringRef Name); Symbol ns(llvm::StringRef Name); // Create a C++20 concept symbol. Symbol conceptSym(llvm::StringRef Name); +// Create a macro symbol. +Symbol macro(llvm::StringRef Name, llvm::StringRef ArgList = {}); // Create an Objective-C symbol. Symbol objcSym(llvm::StringRef Name, index::SymbolKind Kind, diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index b66be44e9f8a6f924768759faf27dc34410ecbf4..4dfbd8ca49ab9b53d487946cbe1cb93a2c3a1a06 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -100,6 +100,8 @@ Improvements to clang-tidy - Improved :program:`run-clang-tidy.py` script. Added argument `-source-filter` to filter source files from the compilation database, via a RegEx. In a similar fashion to what `-header-filter` does for header files. +- Improved :program:`check_clang_tidy.py` script. Added argument `-export-fixes` + to aid in clang-tidy and test development. New checks ^^^^^^^^^^ @@ -297,6 +299,10 @@ Miscellaneous ``--format`` option is specified. Now :program:`clang-apply-replacements` applies formatting only with the option. +- Fixed the :doc:`linuxkernel-must-check-errs + ` documentation to consistently + use the check's proper name. + Improvements to include-fixer ----------------------------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/linuxkernel/must-use-errs.rst b/clang-tools-extra/docs/clang-tidy/checks/linuxkernel/must-check-errs.rst similarity index 88% rename from clang-tools-extra/docs/clang-tidy/checks/linuxkernel/must-use-errs.rst rename to clang-tools-extra/docs/clang-tidy/checks/linuxkernel/must-check-errs.rst index 8a85426880987ea9ce31c6f10738b01075d15532..cef5a70db309e1b4bca6498d34062d956b680e95 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/linuxkernel/must-use-errs.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/linuxkernel/must-check-errs.rst @@ -1,7 +1,7 @@ -.. title:: clang-tidy - linuxkernel-must-use-errs +.. title:: clang-tidy - linuxkernel-must-check-errs -linuxkernel-must-use-errs -========================= +linuxkernel-must-check-errs +=========================== Checks Linux kernel code to see if it uses the results from the functions in ``linux/err.h``. Also checks to see if code uses the results from functions that diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 188a42bfddd383619ed1e143543bf5a5201c7881..8bc46acad56c8416ba8fad3bf592be0fc021e20e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -233,7 +233,7 @@ Clang-Tidy Checks :doc:`hicpp-multiway-paths-covered `, :doc:`hicpp-no-assembler `, :doc:`hicpp-signed-bitwise `, - :doc:`linuxkernel-must-use-errs `, + :doc:`linuxkernel-must-check-errs `, :doc:`llvm-header-guard `, :doc:`llvm-include-order `, "Yes" :doc:`llvm-namespace-comment `, diff --git a/clang-tools-extra/test/clang-tidy/check_clang_tidy.py b/clang-tools-extra/test/clang-tidy/check_clang_tidy.py index 53ffca0bad8d06fd92d0e9c5663ecc8acc464208..6d4b466afa691a74b59185e360f0b9a8b6597261 100755 --- a/clang-tools-extra/test/clang-tidy/check_clang_tidy.py +++ b/clang-tools-extra/test/clang-tidy/check_clang_tidy.py @@ -8,25 +8,35 @@ # # ===------------------------------------------------------------------------===# -r""" +""" ClangTidy Test Helper ===================== -This script runs clang-tidy in fix mode and verify fixes, messages or both. +This script is used to simplify writing, running, and debugging tests compatible +with llvm-lit. By default it runs clang-tidy in fix mode and uses FileCheck to +verify messages and/or fixes. + +For debugging, with --export-fixes, the tool simply exports fixes to a provided +file and does not run FileCheck. -Usage: - check_clang_tidy.py [-resource-dir=] \ - [-assume-filename=] \ - [-check-suffix=] \ - [-check-suffixes=] \ - [-std=c++(98|11|14|17|20)[-or-later]] \ - \ - -- [optional clang-tidy arguments] +Extra arguments, those after the first -- if any, are passed to either +clang-tidy or clang: +* Arguments between the first -- and second -- are clang-tidy arguments. + * May be only whitespace if there are no clang-tidy arguments. + * clang-tidy's --config would go here. +* Arguments after the second -- are clang arguments + +Examples +-------- -Example: // RUN: %check_clang_tidy %s llvm-include-order %t -- -- -isystem %S/Inputs -Notes: +or + + // RUN: %check_clang_tidy %s llvm-include-order --export-fixes=fixes.yaml %t -std=c++20 + +Notes +----- -std=c++(98|11|14|17|20)-or-later: This flag will cause multiple runs within the same check_clang_tidy execution. Make sure you don't have shared state across these runs. @@ -34,6 +44,7 @@ Notes: import argparse import os +import pathlib import re import subprocess import sys @@ -88,6 +99,7 @@ class CheckRunner: self.has_check_fixes = False self.has_check_messages = False self.has_check_notes = False + self.export_fixes = args.export_fixes self.fixes = MessagePrefix("CHECK-FIXES") self.messages = MessagePrefix("CHECK-MESSAGES") self.notes = MessagePrefix("CHECK-NOTES") @@ -181,7 +193,13 @@ class CheckRunner: [ "clang-tidy", self.temp_file_name, - "-fix", + ] + + [ + "-fix" + if self.export_fixes is None + else "--export-fixes=" + self.export_fixes + ] + + [ "--checks=-*," + self.check_name, ] + self.clang_tidy_extra_args @@ -255,12 +273,14 @@ class CheckRunner: def run(self): self.read_input() - self.get_prefixes() + if self.export_fixes is None: + self.get_prefixes() self.prepare_test_inputs() clang_tidy_output = self.run_clang_tidy() - self.check_fixes() - self.check_messages(clang_tidy_output) - self.check_notes(clang_tidy_output) + if self.export_fixes is None: + self.check_fixes() + self.check_messages(clang_tidy_output) + self.check_notes(clang_tidy_output) def expand_std(std): @@ -284,7 +304,11 @@ def csv(string): def parse_arguments(): - parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser( + prog=pathlib.Path(__file__).stem, + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) parser.add_argument("-expect-clang-tidy-error", action="store_true") parser.add_argument("-resource-dir") parser.add_argument("-assume-filename") @@ -298,7 +322,19 @@ def parse_arguments(): type=csv, help="comma-separated list of FileCheck suffixes", ) - parser.add_argument("-std", type=csv, default=["c++11-or-later"]) + parser.add_argument( + "-export-fixes", + default=None, + type=str, + metavar="file", + help="A file to export fixes into instead of fixing.", + ) + parser.add_argument( + "-std", + type=csv, + default=["c++11-or-later"], + help="Passed to clang. Special -or-later values are expanded.", + ) return parser.parse_known_args() diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index 284b2af24ddaa0405398e8ea1826856e93401ba6..f092766fa19f07f754960ec9524078d6b65070d4 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -165,6 +165,13 @@ if(CLANG_ENABLE_LIBXML2) endif() endif() +if(CLANG_ENABLE_CIR) + if (NOT "${LLVM_ENABLE_PROJECTS}" MATCHES "MLIR|mlir") + message(FATAL_ERROR + "Cannot build ClangIR without MLIR in LLVM_ENABLE_PROJECTS") + endif() +endif() + include(CheckIncludeFile) check_include_file(sys/resource.h CLANG_HAVE_RLIMITS) diff --git a/clang/cmake/caches/Release.cmake b/clang/cmake/caches/Release.cmake index 1ca9138b98073118184385ba6eb6a8a0690132ad..bd1f688d61a7ea2aaa475aaec7d6a0970c12139f 100644 --- a/clang/cmake/caches/Release.cmake +++ b/clang/cmake/caches/Release.cmake @@ -4,7 +4,7 @@ # General Options set(LLVM_RELEASE_ENABLE_LTO THIN CACHE STRING "") -set(LLVM_RELEASE_ENABLE_PGO ON CACHE BOOL "") +set(LLVM_RELEASE_ENABLE_PGO OFF CACHE BOOL "") set(CMAKE_BUILD_TYPE RELEASE CACHE STRING "") diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst index 80dc38a075c8fcf572ce093da3893007e23342b4..dbd9c91ae508e5d8175c5e1734e4fcdb34c80090 100644 --- a/clang/docs/ClangFormat.rst +++ b/clang/docs/ClangFormat.rst @@ -54,7 +54,7 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# code. Objective-C: .m .mm Proto: .proto .protodevel TableGen: .td - TextProto: .textpb .pb.txt .textproto .asciipb + TextProto: .txtpb .textpb .pb.txt .textproto .asciipb Verilog: .sv .svh .v .vh --cursor= - The position of the cursor when invoking clang-format from an editor integration diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 7b23e4d1c2f30c1544b2eba17b2a53849a6bc6a9..05c8f765b556951a51febff0515b5b4904fec2c3 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1493,6 +1493,7 @@ Conditional ``explicit`` __cpp_conditional_explicit C+ ``if consteval`` __cpp_if_consteval C++23 C++20 ``static operator()`` __cpp_static_call_operator C++23 C++03 Attributes on Lambda-Expressions C++23 C++11 +``= delete ("should have a reason");`` __cpp_deleted_function C++26 C++03 -------------------------------------------- -------------------------------- ------------- ------------- Designated initializers (N494) C99 C89 Array & element qualification (N2607) C23 C89 @@ -1610,6 +1611,7 @@ The following type trait primitives are supported by Clang. Those traits marked * ``__is_pod`` (C++, GNU, Microsoft, Embarcadero): Note, the corresponding standard trait was deprecated in C++20. * ``__is_pointer`` (C++, Embarcadero) +* ``__is_pointer_interconvertible_base_of`` (C++, GNU, Microsoft) * ``__is_polymorphic`` (C++, GNU, Microsoft, Embarcadero) * ``__is_reference`` (C++, Embarcadero) * ``__is_referenceable`` (C++, GNU, Microsoft, Embarcadero): diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 45a9a79739a4eb3bf2930852243d890aac0228be..76701dc723b6c344cf113f8ab10d76d40ba3c4af 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -98,7 +98,8 @@ C++20 Feature Support behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'. (#GH79240). -- Implemented the `__is_layout_compatible` intrinsic to support +- Implemented the `__is_layout_compatible` and `__is_pointer_interconvertible_base_of` + intrinsics to support `P0466R5: Layout-compatibility and Pointer-interconvertibility Traits `_. - Clang now implements [module.import]p7 fully. Clang now will import module @@ -128,6 +129,8 @@ C++2c Feature Support - Implemented `P2662R3 Pack Indexing `_. +- Implemented `P2573R2: = delete("should have a reason"); `_ + Resolutions to C++ Defect Reports ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -526,8 +529,6 @@ Bug Fixes to C++ Support - Fix an issue caused by not handling invalid cases when substituting into the parameter mapping of a constraint. Fixes (#GH86757). - Fixed a bug that prevented member function templates of class templates declared with a deduced return type from being explicitly specialized for a given implicit instantiation of the class template. -- Fixed a crash when ``this`` is used in a dependent class scope function template specialization - that instantiates to a static member function. - Fix crash when inheriting from a cv-qualified type. Fixes: (`#35603 `_) @@ -536,6 +537,8 @@ Bug Fixes to C++ Support - Clang now correctly tracks type dependence of by-value captures in lambdas with an explicit object parameter. Fixes (#GH70604), (#GH79754), (#GH84163), (#GH84425), (#GH86054), (#GH86398), and (#GH86399). +- Fix a crash when deducing ``auto`` from an invalid dereference (#GH88329). +- Fix a crash in requires expression with templated base class member function. Fixes (#GH84020). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index 94e7dd817809dd2e09c34ed71f819ddccc13db63..f5c47d8a7c2113ab5e3303fda5e86dbb27f029d2 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -243,7 +243,8 @@ public: void Visit(const OpenACCClause *C) { getNodeDelegate().AddChild([=] { getNodeDelegate().Visit(C); - // TODO OpenACC: Switch on clauses that have children, and add them. + for (const auto *S : C->children()) + Visit(S); }); } @@ -932,6 +933,14 @@ public: Visit(TArg); } + void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) { + Visit(Node->getExpr()); + } + + void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) { + Visit(Node->getExpr()); + } + // Implements Visit methods for Attrs. #include "clang/AST/AttrNodeTraverse.inc" }; diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index ed6790acdfc7cca7598f8a1473f68d1ec1748e1a..01af50ca694fdd8611bd3bb08573d9fe1622d6b7 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -1993,21 +1993,35 @@ public: }; - /// Stashed information about a defaulted function definition whose body has - /// not yet been lazily generated. - class DefaultedFunctionInfo final - : llvm::TrailingObjects { + /// Stashed information about a defaulted/deleted function body. + class DefaultedOrDeletedFunctionInfo final + : llvm::TrailingObjects { friend TrailingObjects; unsigned NumLookups; + bool HasDeletedMessage; + + size_t numTrailingObjects(OverloadToken) const { + return NumLookups; + } public: - static DefaultedFunctionInfo *Create(ASTContext &Context, - ArrayRef Lookups); + static DefaultedOrDeletedFunctionInfo * + Create(ASTContext &Context, ArrayRef Lookups, + StringLiteral *DeletedMessage = nullptr); + /// Get the unqualified lookup results that should be used in this /// defaulted function definition. ArrayRef getUnqualifiedLookups() const { return {getTrailingObjects(), NumLookups}; } + + StringLiteral *getDeletedMessage() const { + return HasDeletedMessage ? *getTrailingObjects() + : nullptr; + } + + void setDeletedMessage(StringLiteral *Message); }; private: @@ -2017,12 +2031,12 @@ private: ParmVarDecl **ParamInfo = nullptr; /// The active member of this union is determined by - /// FunctionDeclBits.HasDefaultedFunctionInfo. + /// FunctionDeclBits.HasDefaultedOrDeletedInfo. union { /// The body of the function. LazyDeclStmtPtr Body; /// Information about a future defaulted function definition. - DefaultedFunctionInfo *DefaultedInfo; + DefaultedOrDeletedFunctionInfo *DefaultedOrDeletedInfo; }; unsigned ODRHash; @@ -2280,18 +2294,18 @@ public: /// Returns whether this specific declaration of the function has a body. bool doesThisDeclarationHaveABody() const { - return (!FunctionDeclBits.HasDefaultedFunctionInfo && Body) || + return (!FunctionDeclBits.HasDefaultedOrDeletedInfo && Body) || isLateTemplateParsed(); } void setBody(Stmt *B); void setLazyBody(uint64_t Offset) { - FunctionDeclBits.HasDefaultedFunctionInfo = false; + FunctionDeclBits.HasDefaultedOrDeletedInfo = false; Body = LazyDeclStmtPtr(Offset); } - void setDefaultedFunctionInfo(DefaultedFunctionInfo *Info); - DefaultedFunctionInfo *getDefaultedFunctionInfo() const; + void setDefaultedOrDeletedInfo(DefaultedOrDeletedFunctionInfo *Info); + DefaultedOrDeletedFunctionInfo *getDefalutedOrDeletedInfo() const; /// Whether this function is variadic. bool isVariadic() const; @@ -2494,7 +2508,7 @@ public: return FunctionDeclBits.IsDeleted && !isDefaulted(); } - void setDeletedAsWritten(bool D = true) { FunctionDeclBits.IsDeleted = D; } + void setDeletedAsWritten(bool D = true, StringLiteral *Message = nullptr); /// Determines whether this function is "main", which is the /// entry point into an executable program. @@ -2650,6 +2664,13 @@ public: AC.push_back(TRC); } + /// Get the message that indicates why this function was deleted. + StringLiteral *getDeletedMessage() const { + return FunctionDeclBits.HasDefaultedOrDeletedInfo + ? DefaultedOrDeletedInfo->getDeletedMessage() + : nullptr; + } + void setPreviousDeclaration(FunctionDecl * PrevDecl); FunctionDecl *getCanonicalDecl() override; diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 858450926455c602030671323257a4470bc096f7..2194d268fa86f0918112cec6d8e7301eeb6d97f3 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -1739,7 +1739,7 @@ class DeclContext { LLVM_PREFERRED_TYPE(bool) uint64_t IsExplicitlyDefaulted : 1; LLVM_PREFERRED_TYPE(bool) - uint64_t HasDefaultedFunctionInfo : 1; + uint64_t HasDefaultedOrDeletedInfo : 1; /// For member functions of complete types, whether this is an ineligible /// special member function or an unselected destructor. See diff --git a/clang/include/clang/AST/JSONNodeDumper.h b/clang/include/clang/AST/JSONNodeDumper.h index 7a60f362650ca0a939a03acb390bef7ae887eb57..55bd583e304e8b515b93fadb3b7da4664efabb5c 100644 --- a/clang/include/clang/AST/JSONNodeDumper.h +++ b/clang/include/clang/AST/JSONNodeDumper.h @@ -310,6 +310,8 @@ public: void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE); void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *ME); void VisitRequiresExpr(const RequiresExpr *RE); + void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node); + void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node); void VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE); void VisitObjCMessageExpr(const ObjCMessageExpr *OME); diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h index 27e4e1a12c98371e550bcf0a8cd73901bde9d471..401b8e904a1b7ae17dc76ae3735557d053d10669 100644 --- a/clang/include/clang/AST/OpenACCClause.h +++ b/clang/include/clang/AST/OpenACCClause.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_OPENACCCLAUSE_H #define LLVM_CLANG_AST_OPENACCCLAUSE_H #include "clang/AST/ASTContext.h" +#include "clang/AST/StmtIterator.h" #include "clang/Basic/OpenACCKinds.h" namespace clang { @@ -34,6 +35,17 @@ public: static bool classof(const OpenACCClause *) { return true; } + using child_iterator = StmtIterator; + using const_child_iterator = ConstStmtIterator; + using child_range = llvm::iterator_range; + using const_child_range = llvm::iterator_range; + + child_range children(); + const_child_range children() const { + auto Children = const_cast(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + virtual ~OpenACCClause() = default; }; @@ -49,6 +61,13 @@ protected: public: SourceLocation getLParenLoc() const { return LParenLoc; } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; /// A 'default' clause, has the optional 'none' or 'present' argument. @@ -81,6 +100,51 @@ public: SourceLocation EndLoc); }; +/// Represents one of the handful of classes that has an optional/required +/// 'condition' expression as an argument. +class OpenACCClauseWithCondition : public OpenACCClauseWithParams { + Expr *ConditionExpr = nullptr; + +protected: + OpenACCClauseWithCondition(OpenACCClauseKind K, SourceLocation BeginLoc, + SourceLocation LParenLoc, Expr *ConditionExpr, + SourceLocation EndLoc) + : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc), + ConditionExpr(ConditionExpr) {} + +public: + bool hasConditionExpr() const { return ConditionExpr; } + const Expr *getConditionExpr() const { return ConditionExpr; } + Expr *getConditionExpr() { return ConditionExpr; } + + child_range children() { + if (ConditionExpr) + return child_range(reinterpret_cast(&ConditionExpr), + reinterpret_cast(&ConditionExpr + 1)); + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + if (ConditionExpr) + return const_child_range( + reinterpret_cast(&ConditionExpr), + reinterpret_cast(&ConditionExpr + 1)); + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// An 'if' clause, which has a required condition expression. +class OpenACCIfClause : public OpenACCClauseWithCondition { +protected: + OpenACCIfClause(SourceLocation BeginLoc, SourceLocation LParenLoc, + Expr *ConditionExpr, SourceLocation EndLoc); + +public: + static OpenACCIfClause *Create(const ASTContext &C, SourceLocation BeginLoc, + SourceLocation LParenLoc, Expr *ConditionExpr, + SourceLocation EndLoc); +}; + template class OpenACCClauseVisitor { Impl &getDerived() { return static_cast(*this); } @@ -96,7 +160,10 @@ public: switch (C->getClauseKind()) { case OpenACCClauseKind::Default: - VisitOpenACCDefaultClause(*cast(C)); + VisitDefaultClause(*cast(C)); + return; + case OpenACCClauseKind::If: + VisitIfClause(*cast(C)); return; case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: @@ -106,7 +173,6 @@ public: case OpenACCClauseKind::Worker: case OpenACCClauseKind::Vector: case OpenACCClauseKind::NoHost: - case OpenACCClauseKind::If: case OpenACCClauseKind::Self: case OpenACCClauseKind::Copy: case OpenACCClauseKind::UseDevice: @@ -145,9 +211,13 @@ public: llvm_unreachable("Invalid Clause kind"); } - void VisitOpenACCDefaultClause(const OpenACCDefaultClause &Clause) { - return getDerived().VisitOpenACCDefaultClause(Clause); +#define VISIT_CLAUSE(CLAUSE_NAME) \ + void Visit##CLAUSE_NAME##Clause( \ + const OpenACC##CLAUSE_NAME##Clause &Clause) { \ + return getDerived().Visit##CLAUSE_NAME##Clause(Clause); \ } + +#include "clang/Basic/OpenACCClauses.def" }; class OpenACCClausePrinter final @@ -165,7 +235,9 @@ public: } OpenACCClausePrinter(raw_ostream &OS) : OS(OS) {} - void VisitOpenACCDefaultClause(const OpenACCDefaultClause &Clause); +#define VISIT_CLAUSE(CLAUSE_NAME) \ + void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &Clause); +#include "clang/Basic/OpenACCClauses.def" }; } // namespace clang diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 0ca4ea377fc36aca742d155d53edb072474ab255..a0bbe5861c5722dea021d62fb609ec98b5db7031 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -1604,27 +1604,40 @@ specifies availability for the current target platform, the availability attributes are ignored. Supported platforms are: ``ios`` - Apple's iOS operating system. The minimum deployment target is specified by - the ``-mios-version-min=*version*`` or ``-miphoneos-version-min=*version*`` - command-line arguments. + Apple's iOS operating system. The minimum deployment target is specified + as part of the ``-target *arch*-apple-ios*version*`` command line argument. + Alternatively, it can be specified by the ``-mtargetos=ios*version*`` + command-line argument. ``macos`` - Apple's macOS operating system. The minimum deployment target is - specified by the ``-mmacosx-version-min=*version*`` command-line argument. - ``macosx`` is supported for backward-compatibility reasons, but it is - deprecated. + Apple's macOS operating system. The minimum deployment target is specified + as part of the ``-target *arch*-apple-macos*version*`` command line argument. + Alternatively, it can be specified by the ``-mtargetos=macos*version*`` + command-line argument. ``macosx`` is supported for + backward-compatibility reasons, but it is deprecated. ``tvos`` - Apple's tvOS operating system. The minimum deployment target is specified by - the ``-mtvos-version-min=*version*`` command-line argument. + Apple's tvOS operating system. The minimum deployment target is specified + as part of the ``-target *arch*-apple-tvos*version*`` command line argument. + Alternatively, it can be specified by the ``-mtargetos=tvos*version*`` + command-line argument. ``watchos`` - Apple's watchOS operating system. The minimum deployment target is specified by - the ``-mwatchos-version-min=*version*`` command-line argument. + Apple's watchOS operating system. The minimum deployment target is specified + as part of the ``-target *arch*-apple-watchos*version*`` command line argument. + Alternatively, it can be specified by the ``-mtargetos=watchos*version*`` + command-line argument. + +``visionos`` + Apple's visionOS operating system. The minimum deployment target is specified + as part of the ``-target *arch*-apple-visionos*version*`` command line argument. + Alternatively, it can be specified by the ``-mtargetos=visionos*version*`` + command-line argument. ``driverkit`` Apple's DriverKit userspace kernel extensions. The minimum deployment target - is specified as part of the triple. + is specified as part of the ``-target *arch*-apple-driverkit*version*`` + command line argument. A declaration can typically be used even when deploying back to a platform version prior to when the declaration was introduced. When this happens, the @@ -7509,7 +7522,7 @@ means that it can e.g no longer be part of an initializer expression. /* This may print something else than "6 * 7 = 42", if there is a non-weak definition of "ANSWER" in - an object linked in */ + an object linked in */ printf("6 * 7 = %d\n", ANSWER); return 0; diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def index c660582cc98e666031ae1dfbecf9d9b4612c9eae..3e21a2fe2ac6b31cc6bd09644884b2719c13fa3d 100644 --- a/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -61,6 +61,7 @@ BUILTIN(__builtin_amdgcn_s_waitcnt, "vIi", "n") BUILTIN(__builtin_amdgcn_s_sendmsg, "vIiUi", "n") BUILTIN(__builtin_amdgcn_s_sendmsghalt, "vIiUi", "n") BUILTIN(__builtin_amdgcn_s_barrier, "v", "n") +BUILTIN(__builtin_amdgcn_s_ttracedata, "vi", "n") BUILTIN(__builtin_amdgcn_wave_barrier, "v", "n") BUILTIN(__builtin_amdgcn_sched_barrier, "vIi", "n") BUILTIN(__builtin_amdgcn_sched_group_barrier, "vIiIiIi", "n") @@ -267,6 +268,7 @@ TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_bf8_bf8, "fUiUif", "nc", "dot11-insts") TARGET_BUILTIN(__builtin_amdgcn_permlane16, "UiUiUiUiUiIbIb", "nc", "gfx10-insts") TARGET_BUILTIN(__builtin_amdgcn_permlanex16, "UiUiUiUiUiIbIb", "nc", "gfx10-insts") TARGET_BUILTIN(__builtin_amdgcn_mov_dpp8, "UiUiIUi", "nc", "gfx10-insts") +TARGET_BUILTIN(__builtin_amdgcn_s_ttracedata_imm, "vIs", "n", "gfx10-insts") //===----------------------------------------------------------------------===// // Raytracing builtins. diff --git a/clang/include/clang/Basic/Cuda.h b/clang/include/clang/Basic/Cuda.h index 3e77a74c7c0092239c2f9235de9c43b532423ab3..38f30543a0f66268bad94751c2f6944b290369ea 100644 --- a/clang/include/clang/Basic/Cuda.h +++ b/clang/include/clang/Basic/Cuda.h @@ -50,6 +50,10 @@ const char *CudaVersionToString(CudaVersion V); // Input is "Major.Minor" CudaVersion CudaStringToVersion(const llvm::Twine &S); +// We have a name conflict with sys/mac.h on AIX +#ifdef SM_32 +#undef SM_32 +#endif enum class CudaArch { UNUSED, UNKNOWN, @@ -126,6 +130,14 @@ enum class CudaArch { HIPDefault = CudaArch::GFX906, }; +enum class CUDAFunctionTarget { + Device, + Global, + Host, + HostDevice, + InvalidTarget +}; + static inline bool IsNVIDIAGpuArch(CudaArch A) { return A >= CudaArch::SM_20 && A < CudaArch::GFX600; } diff --git a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td index 0a477da7186b09b0f95ba850fb111d970c2eb155..396bff0146a373c94de9bd2c425c13e6c8e59083 100644 --- a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td +++ b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td @@ -20,6 +20,10 @@ def warn_no_such_excluded_header_file : Warning<"no such excluded %select{public def warn_glob_did_not_match: Warning<"glob '%0' did not match any header file">, InGroup; def err_no_such_umbrella_header_file : Error<"%select{public|private|project}1 umbrella header file not found in input: '%0'">; def err_cannot_find_reexport : Error<"cannot find re-exported %select{framework|library}0: '%1'">; +def err_no_matching_target : Error<"no matching target found for target variant '%0'">; +def err_unsupported_vendor : Error<"vendor '%0' is not supported: '%1'">; +def err_unsupported_environment : Error<"environment '%0' is not supported: '%1'">; +def err_unsupported_os : Error<"os '%0' is not supported: '%1'">; } // end of command line category. let CategoryName = "Verification" in { diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 46a44418a3153bc75df0ac7327bab65ac1528bc3..bb9ca2a50cc06c36cbea45f4b4917a382433c7e2 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -941,6 +941,12 @@ def warn_cxx98_compat_defaulted_deleted_function : Warning< "%select{defaulted|deleted}0 function definitions are incompatible with C++98">, InGroup, DefaultIgnore; +def ext_delete_with_message : ExtWarn< + "'= delete' with a message is a C++2c extension">, InGroup; +def warn_cxx23_delete_with_message : Warning< + "'= delete' with a message is incompatible with C++ standards before C++2c">, + DefaultIgnore, InGroup; + // C++11 default member initialization def ext_nonstatic_member_init : ExtWarn< "default member initializer for non-static data member is a C++11 " diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 180e913155d67c6ca037992b13cd092f02994c46..5ec0218aedfe868a48e6eb7b36dd4a26b05fb572 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4683,11 +4683,10 @@ def err_ovl_no_viable_member_function_in_call : Error< "no matching member function for call to %0">; def err_ovl_ambiguous_call : Error< "call to %0 is ambiguous">; -def err_ovl_deleted_call : Error<"call to deleted function %0">; +def err_ovl_deleted_call : Error<"call to deleted" + "%select{| member}0 function %1%select{|: %3}2">; def err_ovl_ambiguous_member_call : Error< "call to member function %0 is ambiguous">; -def err_ovl_deleted_member_call : Error< - "call to deleted member function %0">; def note_ovl_too_many_candidates : Note< "remaining %0 candidate%s0 omitted; " "pass -fshow-overloads=all to show them">; @@ -4915,12 +4914,12 @@ def err_ovl_ambiguous_conversion_in_cast : Error< "dynamic_cast|C-style cast|functional-style cast|}0 from %1 to %2">; def err_ovl_deleted_conversion_in_cast : Error< "%select{|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" - "functional-style cast|}0 from %1 to %2 uses deleted function">; + "functional-style cast|}0 from %1 to %2 uses deleted function%select{|: %4}3">; def err_ovl_ambiguous_init : Error<"call to constructor of %0 is ambiguous">; def err_ref_init_ambiguous : Error< "reference initialization of type %0 with initializer of type %1 is ambiguous">; def err_ovl_deleted_init : Error< - "call to deleted constructor of %0">; + "call to deleted constructor of %0%select{|: %2}1">; def err_ovl_deleted_special_init : Error< "call to implicitly-deleted %select{default constructor|copy constructor|" "move constructor|copy assignment operator|move assignment operator|" @@ -4946,7 +4945,7 @@ def note_ovl_ambiguous_oper_binary_reversed_candidate : Note< def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">; def note_assign_lhs_incomplete : Note<"type %0 is incomplete">; def err_ovl_deleted_oper : Error< - "overload resolution selected deleted operator '%0'">; + "overload resolution selected deleted operator '%0'%select{|: %2}1">; def err_ovl_deleted_special_oper : Error< "object of type %0 cannot be %select{constructed|copied|moved|assigned|" "assigned|destroyed}1 because its %sub{select_special_member_kind}1 is " @@ -4983,7 +4982,7 @@ def err_ovl_ambiguous_object_call : Error< def err_ovl_ambiguous_subscript_call : Error< "call to subscript operator of type %0 is ambiguous">; def err_ovl_deleted_object_call : Error< - "call to deleted function call operator in type %0">; + "call to deleted function call operator in type %0%select{|: %2}1">; def note_ovl_surrogate_cand : Note<"conversion candidate of type %0">; def err_member_call_without_object : Error< "call to %select{non-static|explicit}0 member function without an object argument">; @@ -7588,8 +7587,8 @@ def ext_gnu_ptr_func_arith : Extension< InGroup; def err_readonly_message_assignment : Error< "assigning to 'readonly' return result of an Objective-C message not allowed">; -def ext_integer_increment_complex : Extension< - "ISO C does not support '++'/'--' on complex integer type %0">; +def ext_increment_complex : Extension< + "'%select{--|++}0' on an object of complex type is a Clang extension">; def ext_integer_complement_complex : Extension< "ISO C does not support '~' for complex conjugation of %0">; def err_nosetter_property_assignment : Error< @@ -8284,7 +8283,7 @@ def err_typecheck_nonviable_condition_incomplete : Error< "no viable conversion%diff{ from $ to incomplete type $|}0,1">; def err_typecheck_deleted_function : Error< "conversion function %diff{from $ to $|between types}0,1 " - "invokes a deleted function">; + "invokes a deleted function%select{|: %3}2">; def err_expected_class_or_namespace : Error<"%0 is not a class" "%select{ or namespace|, namespace, or enumeration}1">; @@ -8884,7 +8883,7 @@ def err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector : Error< "address argument to nontemporal builtin must be a pointer to integer, float, " "pointer, or a vector of such types (%0 invalid)">; -def err_deleted_function_use : Error<"attempt to use a deleted function">; +def err_deleted_function_use : Error<"attempt to use a deleted function%select{|: %1}0">; def err_deleted_inherited_ctor_use : Error< "constructor inherited by %0 from base class %1 is implicitly deleted">; diff --git a/clang/include/clang/Basic/OpenACCClauses.def b/clang/include/clang/Basic/OpenACCClauses.def new file mode 100644 index 0000000000000000000000000000000000000000..7fd2720e02ce2283cf7695e5d37c379b7dba2a9d --- /dev/null +++ b/clang/include/clang/Basic/OpenACCClauses.def @@ -0,0 +1,21 @@ +//===-- OpenACCClauses.def - List of implemented OpenACC Clauses -- 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 a list of currently implemented OpenACC Clauses (and +// eventually, the entire list) in a way that makes generating 'visitor' and +// other lists easier. +// +// The primary macro is a single-argument version taking the name of the Clause +// as used in Clang source (so `Default` instead of `default`). +// +// VISIT_CLAUSE(CLAUSE_NAME) + +VISIT_CLAUSE(Default) +VISIT_CLAUSE(If) + +#undef VISIT_CLAUSE diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 800af0e6d0448058d901d396e4f41025610d3b02..a27fbed358a60c2376c938800e477a32e0859fcd 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -521,6 +521,7 @@ TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX) TYPE_TRAIT_1(__has_unique_object_representations, HasUniqueObjectRepresentations, KEYCXX) TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX) +TYPE_TRAIT_2(__is_pointer_interconvertible_base_of, IsPointerInterconvertibleBaseOf, KEYCXX) #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX) #include "clang/Basic/TransformTypeTraits.def" diff --git a/clang/include/clang/CIR/CMakeLists.txt b/clang/include/clang/CIR/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/include/clang/CMakeLists.txt b/clang/include/clang/CMakeLists.txt index 0dc9ea5ed8ac8a48c4fee5856449bf28a8085956..47ac70cd21690f795659acd6f5a95f7e324b9b89 100644 --- a/clang/include/clang/CMakeLists.txt +++ b/clang/include/clang/CMakeLists.txt @@ -1,5 +1,8 @@ add_subdirectory(AST) add_subdirectory(Basic) +if(CLANG_ENABLE_CIR) + add_subdirectory(CIR) +endif() add_subdirectory(Driver) add_subdirectory(Parse) add_subdirectory(Sema) diff --git a/clang/include/clang/CodeGen/CodeGenAction.h b/clang/include/clang/CodeGen/CodeGenAction.h index 7ad2988e589eb2e521a5848dc17090b415b9224e..186dbb43f01ef7cea0cb56d13816608592b8bbb6 100644 --- a/clang/include/clang/CodeGen/CodeGenAction.h +++ b/clang/include/clang/CodeGen/CodeGenAction.h @@ -57,6 +57,8 @@ private: bool loadLinkModules(CompilerInstance &CI); protected: + bool BeginSourceFileAction(CompilerInstance &CI) override; + /// Create a new code generation action. If the optional \p _VMContext /// parameter is supplied, the action uses it without taking ownership, /// otherwise it creates a fresh LLVM context and takes ownership. diff --git a/clang/include/clang/Config/config.h.cmake b/clang/include/clang/Config/config.h.cmake index 4015ac8040861c2cb92d0c79a4334d5d3324dcb3..27ed69e21562bff28e065c3f04cb50159556dd46 100644 --- a/clang/include/clang/Config/config.h.cmake +++ b/clang/include/clang/Config/config.h.cmake @@ -83,4 +83,7 @@ /* Spawn a new process clang.exe for the CC1 tool invocation, when necessary */ #cmakedefine01 CLANG_SPAWN_CC1 +/* Whether CIR is built into Clang */ +#cmakedefine01 CLANG_ENABLE_CIR + #endif diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 7ac36222644aac78e6c90cd8a3826bdce52ddceb..e24626913add7627602398ab4f556b4340ec5d2f 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1341,7 +1341,8 @@ def hip_link : Flag<["--"], "hip-link">, Group, HelpText<"Link clang-offload-bundler bundles for HIP">; def no_hip_rt: Flag<["-"], "no-hip-rt">, Group, HelpText<"Do not link against HIP runtime libraries">; -def rocm_path_EQ : Joined<["--"], "rocm-path=">, Group, +def rocm_path_EQ : Joined<["--"], "rocm-path=">, + Visibility<[FlangOption]>, Group, HelpText<"ROCm installation path, used for finding and automatically linking required bitcode libraries.">; def hip_path_EQ : Joined<["--"], "hip-path=">, Group, HelpText<"HIP runtime installation path, used for finding HIP version and adding HIP include path.">; @@ -3035,6 +3036,7 @@ defm prebuilt_implicit_modules : BoolFOption<"prebuilt-implicit-modules", def fmodule_output_EQ : Joined<["-"], "fmodule-output=">, Flags<[NoXarchOption]>, Visibility<[ClangOption, CC1Option]>, + MarshallingInfoString>, HelpText<"Save intermediate module file results when compiling a standard C++ module unit.">; def fmodule_output : Flag<["-"], "fmodule-output">, Flags<[NoXarchOption]>, Visibility<[ClangOption, CC1Option]>, @@ -3048,6 +3050,11 @@ defm skip_odr_check_in_gmf : BoolOption<"f", "skip-odr-check-in-gmf", "Perform ODR checks for decls in the global module fragment.">>, Group; +def modules_reduced_bmi : Flag<["-"], "fexperimental-modules-reduced-bmi">, + Group, Visibility<[ClangOption, CC1Option]>, + HelpText<"Generate the reduced BMI">, + MarshallingInfoFlag>; + def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, Group, Visibility<[ClangOption, CC1Option]>, MetaVarName<"">, HelpText<"Specify the interval (in seconds) between attempts to prune the module cache">, @@ -5464,21 +5471,23 @@ def rdynamic : Flag<["-"], "rdynamic">, Group, Visibility<[ClangOption, FlangOption]>; def resource_dir : Separate<["-"], "resource-dir">, Flags<[NoXarchOption, HelpHidden]>, - Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>, + Visibility<[ClangOption, CC1Option, CLOption, DXCOption, FlangOption, FC1Option]>, HelpText<"The directory which holds the compiler resource files">, MarshallingInfoString>; def resource_dir_EQ : Joined<["-"], "resource-dir=">, Flags<[NoXarchOption]>, - Visibility<[ClangOption, CLOption, DXCOption]>, + Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, Alias; def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>, Group, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>; def rtlib_EQ : Joined<["-", "--"], "rtlib=">, Visibility<[ClangOption, CLOption]>, HelpText<"Compiler runtime library to use">; def frtlib_add_rpath: Flag<["-"], "frtlib-add-rpath">, Flags<[NoArgumentUnused]>, + Visibility<[ClangOption, FlangOption]>, HelpText<"Add -rpath with architecture-specific resource directory to the linker flags. " "When --hip-link is specified, also add -rpath with HIP runtime library directory to the linker flags">; def fno_rtlib_add_rpath: Flag<["-"], "fno-rtlib-add-rpath">, Flags<[NoArgumentUnused]>, + Visibility<[ClangOption, FlangOption]>, HelpText<"Do not add -rpath with architecture-specific resource directory to the linker flags. " "When --hip-link is specified, do not add -rpath with HIP runtime library directory to the linker flags">; def offload_add_rpath: Flag<["--"], "offload-add-rpath">, diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 5ee4d471670f48bae893ad9da4432923ae305660..a738c1f375768282259993be13e40fcf6ce11ae0 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -404,6 +404,10 @@ public: LLVM_PREFERRED_TYPE(bool) unsigned EmitPrettySymbolGraphs : 1; + /// Whether to generate reduced BMI for C++20 named modules. + LLVM_PREFERRED_TYPE(bool) + unsigned GenReducedBMI : 1; + CodeCompleteOptions CodeCompleteOpts; /// Specifies the output format of the AST. @@ -568,6 +572,9 @@ public: /// Path which stores the output files for -ftime-trace std::string TimeTracePath; + /// Output Path for module output file. + std::string ModuleOutputPath; + public: FrontendOptions() : DisableFree(false), RelocatablePCH(false), ShowHelp(false), @@ -582,7 +589,8 @@ public: AllowPCMWithCompilerErrors(false), ModulesShareFileManager(true), EmitSymbolGraph(false), EmitExtensionSymbolGraphs(false), EmitSymbolGraphSymbolLabelsForTesting(false), - EmitPrettySymbolGraphs(false), TimeTraceGranularity(500) {} + EmitPrettySymbolGraphs(false), GenReducedBMI(false), + TimeTraceGranularity(500) {} /// getInputKindForExtension - Return the appropriate input kind for a file /// extension. For example, "c" would return Language::C. diff --git a/clang/include/clang/InstallAPI/DylibVerifier.h b/clang/include/clang/InstallAPI/DylibVerifier.h index a3df25f10de4b13f311c0b790c3503bd83e8f53a..31de212fc423a5e8548d894c2ac26e3a4a225ae8 100644 --- a/clang/include/clang/InstallAPI/DylibVerifier.h +++ b/clang/include/clang/InstallAPI/DylibVerifier.h @@ -28,6 +28,16 @@ enum class VerificationMode { using LibAttrs = llvm::StringMap; using ReexportedInterfaces = llvm::SmallVector; +// Pointers to information about a zippered declaration used for +// querying and reporting violations against different +// declarations that all map to the same symbol. +struct ZipperedDeclSource { + const FrontendAttrs *FA; + clang::SourceManager *SrcMgr; + Target T; +}; +using ZipperedDeclSources = std::vector; + /// Service responsible to tracking state of verification across the /// lifetime of InstallAPI. /// As declarations are collected during AST traversal, they are @@ -68,10 +78,10 @@ public: DylibVerifier() = default; DylibVerifier(llvm::MachO::Records &&Dylib, ReexportedInterfaces &&Reexports, - DiagnosticsEngine *Diag, VerificationMode Mode, bool Demangle, - StringRef DSYMPath) + DiagnosticsEngine *Diag, VerificationMode Mode, bool Zippered, + bool Demangle, StringRef DSYMPath) : Dylib(std::move(Dylib)), Reexports(std::move(Reexports)), Mode(Mode), - Demangle(Demangle), DSYMPath(DSYMPath), + Zippered(Zippered), Demangle(Demangle), DSYMPath(DSYMPath), Exports(std::make_unique()), Ctx(VerifierContext{Diag}) {} Result verify(GlobalRecord *R, const FrontendAttrs *FA); @@ -118,6 +128,15 @@ private: /// symbols should be omitted from the text-api file. bool shouldIgnoreReexport(const Record *R, SymbolContext &SymCtx) const; + // Ignore and omit unavailable symbols in zippered libraries. + bool shouldIgnoreZipperedAvailability(const Record *R, SymbolContext &SymCtx); + + // Check if an internal declaration in zippered library has an + // external declaration for a different platform. This results + // in the symbol being in a "seperate" platform slice. + bool shouldIgnoreInternalZipperedSymbol(const Record *R, + const SymbolContext &SymCtx) const; + /// Compare the visibility declarations to the linkage of symbol found in /// dylib. Result compareVisibility(const Record *R, SymbolContext &SymCtx, @@ -173,6 +192,9 @@ private: // Controls what class of violations to report. VerificationMode Mode = VerificationMode::Invalid; + // Library is zippered. + bool Zippered = false; + // Attempt to demangle when reporting violations. bool Demangle = false; @@ -182,6 +204,10 @@ private: // Valid symbols in final text file. std::unique_ptr Exports = std::make_unique(); + // Unavailable or obsoleted declarations for a zippered library. + // These are cross referenced against symbols in the dylib. + llvm::StringMap DeferredZipperedSymbols; + // Track current state of verification while traversing AST. VerifierContext Ctx; diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h index 855f81f775f8a83bedb0fcdb490ec18ba404cdd5..c5f90ef4cb3682a35f0869f81ff3f5a433ca396f 100644 --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -547,14 +547,15 @@ public: /// Return whether the specified file is a normal header, /// a system header, or a C++ friendly system header. SrcMgr::CharacteristicKind getFileDirFlavor(FileEntryRef File) { - return (SrcMgr::CharacteristicKind)getFileInfo(File).DirInfo; + if (const HeaderFileInfo *HFI = getExistingFileInfo(File)) + return (SrcMgr::CharacteristicKind)HFI->DirInfo; + return (SrcMgr::CharacteristicKind)HeaderFileInfo().DirInfo; } /// Mark the specified file as a "once only" file due to /// \#pragma once. void MarkFileIncludeOnce(FileEntryRef File) { - HeaderFileInfo &FI = getFileInfo(File); - FI.isPragmaOnce = true; + getFileInfo(File).isPragmaOnce = true; } /// Mark the specified file as a system header, e.g. due to @@ -834,16 +835,17 @@ public: unsigned header_file_size() const { return FileInfo.size(); } - /// Return the HeaderFileInfo structure for the specified FileEntry, - /// in preparation for updating it in some way. + /// Return the HeaderFileInfo structure for the specified FileEntry, in + /// preparation for updating it in some way. HeaderFileInfo &getFileInfo(FileEntryRef FE); - /// Return the HeaderFileInfo structure for the specified FileEntry, - /// if it has ever been filled in. - /// \param WantExternal Whether the caller wants purely-external header file - /// info (where \p External is true). - const HeaderFileInfo *getExistingFileInfo(FileEntryRef FE, - bool WantExternal = true) const; + /// Return the HeaderFileInfo structure for the specified FileEntry, if it has + /// ever been filled in (either locally or externally). + const HeaderFileInfo *getExistingFileInfo(FileEntryRef FE) const; + + /// Return the headerFileInfo structure for the specified FileEntry, if it has + /// ever been filled in locally. + const HeaderFileInfo *getExistingLocalFileInfo(FileEntryRef FE) const; SearchDirIterator search_dir_begin() { return {*this, 0}; } SearchDirIterator search_dir_end() { return {*this, SearchDirs.size()}; } diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 3a055c10ffb3877717a2e97b020523178bfb6c41..5950dd74cfe83c7f2457a12b7fd27253bdf2a7cd 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1601,6 +1601,8 @@ private: const ParsedTemplateInfo &TemplateInfo, const VirtSpecifiers &VS, SourceLocation PureSpecLoc); + StringLiteral *ParseCXXDeletedFunctionMessage(); + void SkipDeletedFunctionBody(); void ParseCXXNonStaticMemberInitializer(Decl *VarD); void ParseLexedAttributes(ParsingClass &Class); void ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, @@ -3657,6 +3659,8 @@ private: bool ParseOpenACCGangArgList(); /// Parses a 'gang-arg', used for the 'gang' clause. bool ParseOpenACCGangArg(); + /// Parses a 'condition' expr, ensuring it results in a + ExprResult ParseOpenACCConditionExpr(); private: //===--------------------------------------------------------------------===// diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 351b8e1f31134fe87920acfd9e651f789e7080af..d93ac7863b721dc783aaabdc91b575b93b96a41c 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -38,6 +38,7 @@ #include "clang/AST/TypeOrdering.h" #include "clang/Basic/BitmaskEnum.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/Cuda.h" #include "clang/Basic/DarwinSDKInfo.h" #include "clang/Basic/ExpressionTraits.h" #include "clang/Basic/Module.h" @@ -60,6 +61,7 @@ #include "clang/Sema/TypoCorrection.h" #include "clang/Sema/Weak.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallPtrSet.h" @@ -182,6 +184,7 @@ class Preprocessor; class PseudoDestructorTypeStorage; class PseudoObjectExpr; class QualType; +class SemaCUDA; class SemaHLSL; class SemaOpenACC; class SemaSYCL; @@ -423,6 +426,17 @@ enum class TemplateDeductionResult { AlreadyDiagnosed }; +/// Kinds of C++ special members. +enum class CXXSpecialMemberKind { + DefaultConstructor, + CopyConstructor, + MoveConstructor, + CopyAssignment, + MoveAssignment, + Destructor, + Invalid +}; + /// Sema - This implements semantic analysis and AST building for C. /// \nosubgrouping class Sema final : public SemaBase { @@ -466,8 +480,7 @@ class Sema final : public SemaBase { // 35. Code Completion (SemaCodeComplete.cpp) // 36. FixIt Helpers (SemaFixItUtils.cpp) // 37. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) - // 38. CUDA (SemaCUDA.cpp) - // 39. OpenMP Directives and Clauses (SemaOpenMP.cpp) + // 38. OpenMP Directives and Clauses (SemaOpenMP.cpp) /// \name Semantic Analysis /// Implementations are in Sema.cpp @@ -961,9 +974,19 @@ public: return DelayedDiagnostics.push(pool); } + /// Diagnostics that are emitted only if we discover that the given function + /// must be codegen'ed. Because handling these correctly adds overhead to + /// compilation, this is currently only enabled for CUDA compilations. + SemaDiagnosticBuilder::DeferredDiagnosticsType DeviceDeferredDiags; + /// CurContext - This is the current declaration context of parsing. DeclContext *CurContext; + SemaCUDA &CUDA() { + assert(CUDAPtr); + return *CUDAPtr; + } + SemaHLSL &HLSL() { assert(HLSLPtr); return *HLSLPtr; @@ -1009,6 +1032,7 @@ private: mutable IdentifierInfo *Ident_super; + std::unique_ptr CUDAPtr; std::unique_ptr HLSLPtr; std::unique_ptr OpenACCPtr; std::unique_ptr SYCLPtr; @@ -1975,6 +1999,8 @@ public: }; bool IsLayoutCompatible(QualType T1, QualType T2) const; + bool IsPointerInterconvertibleBaseOf(const TypeSourceInfo *Base, + const TypeSourceInfo *Derived); bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, const FunctionProtoType *Proto); @@ -2940,13 +2966,6 @@ public: QualType NewT, QualType OldT); void CheckMain(FunctionDecl *FD, const DeclSpec &D); void CheckMSVCRTEntryPoint(FunctionDecl *FD); - void ActOnHLSLTopLevelFunction(FunctionDecl *FD); - void CheckHLSLEntryPoint(FunctionDecl *FD); - void CheckHLSLSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, - const HLSLAnnotationAttr *AnnotationAttr); - void DiagnoseHLSLAttrStageMismatch( - const Attr *A, HLSLShaderAttr::ShaderType Stage, - std::initializer_list AllowedStages); Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, bool IsDefinition); void CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D); @@ -3026,14 +3045,18 @@ public: void ActOnDocumentableDecls(ArrayRef Group); enum class FnBodyKind { - /// C++ [dcl.fct.def.general]p1 + /// C++26 [dcl.fct.def.general]p1 /// function-body: /// ctor-initializer[opt] compound-statement /// function-try-block Other, /// = default ; Default, + /// deleted-function-body + /// + /// deleted-function-body: /// = delete ; + /// = delete ( unevaluated-string ) ; Delete }; @@ -3658,20 +3681,12 @@ public: InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const InternalLinkageAttr &AL); - enum CUDAFunctionTarget { - CFT_Device, - CFT_Global, - CFT_Host, - CFT_HostDevice, - CFT_InvalidTarget - }; - /// Check validaty of calling convention attribute \p attr. If \p FD /// is not null pointer, use \p FD to determine the CUDA/HIP host/device /// target. Otherwise, it is specified by \p CFT. - bool CheckCallingConvAttr(const ParsedAttr &attr, CallingConv &CC, - const FunctionDecl *FD = nullptr, - CUDAFunctionTarget CFT = CFT_InvalidTarget); + bool CheckCallingConvAttr( + const ParsedAttr &attr, CallingConv &CC, const FunctionDecl *FD = nullptr, + CUDAFunctionTarget CFT = CUDAFunctionTarget::InvalidTarget); void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI, ParameterABI ABI); @@ -3708,14 +3723,6 @@ public: StringRef UuidAsWritten, MSGuidDecl *GuidDecl); BTFDeclTagAttr *mergeBTFDeclTagAttr(Decl *D, const BTFDeclTagAttr &AL); - HLSLNumThreadsAttr *mergeHLSLNumThreadsAttr(Decl *D, - const AttributeCommonInfo &AL, - int X, int Y, int Z); - HLSLShaderAttr *mergeHLSLShaderAttr(Decl *D, const AttributeCommonInfo &AL, - HLSLShaderAttr::ShaderType ShaderType); - HLSLParamModifierAttr * - mergeHLSLParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, - HLSLParamModifierAttr::Spelling Spelling); WebAssemblyImportNameAttr * mergeImportNameAttr(Decl *D, const WebAssemblyImportNameAttr &AL); @@ -4092,22 +4099,11 @@ public: SourceRange SpecificationRange, ArrayRef DynamicExceptions, ArrayRef DynamicExceptionRanges, Expr *NoexceptExpr); - /// Kinds of C++ special members. - enum CXXSpecialMember { - CXXDefaultConstructor, - CXXCopyConstructor, - CXXMoveConstructor, - CXXCopyAssignment, - CXXMoveAssignment, - CXXDestructor, - CXXInvalid - }; - class InheritedConstructorInfo; /// Determine if a special member function should have a deleted /// definition when it is defaulted. - bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, + bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMemberKind CSM, InheritedConstructorInfo *ICI = nullptr, bool Diagnose = false); @@ -4473,7 +4469,7 @@ public: void CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *MD); bool CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, - CXXSpecialMember CSM, + CXXSpecialMemberKind CSM, SourceLocation DefaultLoc); void CheckDelayedMemberExceptionSpecs(); @@ -4633,7 +4629,7 @@ public: void CheckCXXDefaultArguments(FunctionDecl *FD); void CheckExtraCXXDefaultArguments(Declarator &D); - CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD) { + CXXSpecialMemberKind getSpecialMember(const CXXMethodDecl *MD) { return getDefaultedFunctionKind(MD).asSpecialMember(); } @@ -4660,7 +4656,8 @@ public: AccessSpecifier AS, const ParsedAttr &MSPropertyAttr); - void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMember CSM); + void DiagnoseNontrivial(const CXXRecordDecl *Record, + CXXSpecialMemberKind CSM); enum TrivialABIHandling { /// The triviality of a method unaffected by "trivial_abi". @@ -4670,26 +4667,31 @@ public: TAH_ConsiderTrivialABI }; - bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, + bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMemberKind CSM, TrivialABIHandling TAH = TAH_IgnoreTrivialABI, bool Diagnose = false); /// For a defaulted function, the kind of defaulted function that it is. class DefaultedFunctionKind { + LLVM_PREFERRED_TYPE(CXXSpecialMemberKind) unsigned SpecialMember : 8; unsigned Comparison : 8; public: DefaultedFunctionKind() - : SpecialMember(CXXInvalid), + : SpecialMember(llvm::to_underlying(CXXSpecialMemberKind::Invalid)), Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) {} - DefaultedFunctionKind(CXXSpecialMember CSM) - : SpecialMember(CSM), + DefaultedFunctionKind(CXXSpecialMemberKind CSM) + : SpecialMember(llvm::to_underlying(CSM)), Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) {} DefaultedFunctionKind(DefaultedComparisonKind Comp) - : SpecialMember(CXXInvalid), Comparison(llvm::to_underlying(Comp)) {} + : SpecialMember(llvm::to_underlying(CXXSpecialMemberKind::Invalid)), + Comparison(llvm::to_underlying(Comp)) {} - bool isSpecialMember() const { return SpecialMember != CXXInvalid; } + bool isSpecialMember() const { + return static_cast(SpecialMember) != + CXXSpecialMemberKind::Invalid; + } bool isComparison() const { return static_cast(Comparison) != DefaultedComparisonKind::None; @@ -4699,8 +4701,8 @@ public: return isSpecialMember() || isComparison(); } - CXXSpecialMember asSpecialMember() const { - return static_cast(SpecialMember); + CXXSpecialMemberKind asSpecialMember() const { + return static_cast(SpecialMember); } DefaultedComparisonKind asComparison() const { return static_cast(Comparison); @@ -4708,7 +4710,8 @@ public: /// Get the index of this function kind for use in diagnostics. unsigned getDiagnosticIndex() const { - static_assert(CXXInvalid > CXXDestructor, + static_assert(llvm::to_underlying(CXXSpecialMemberKind::Invalid) > + llvm::to_underlying(CXXSpecialMemberKind::Destructor), "invalid should have highest index"); static_assert((unsigned)DefaultedComparisonKind::None == 0, "none should be equal to zero"); @@ -4752,10 +4755,12 @@ public: SourceLocation EqualLoc); void ActOnPureSpecifier(Decl *D, SourceLocation PureSpecLoc); - void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc); + void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc, + StringLiteral *Message = nullptr); void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc); - void SetFunctionBodyKind(Decl *D, SourceLocation Loc, FnBodyKind BodyKind); + void SetFunctionBodyKind(Decl *D, SourceLocation Loc, FnBodyKind BodyKind, + StringLiteral *DeletedMessage = nullptr); void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D); ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr); ExprResult ActOnRequiresClause(ExprResult ConstraintExpr); @@ -4814,7 +4819,7 @@ public: /// definition in this translation unit. llvm::MapVector UndefinedButUsed; - typedef llvm::PointerIntPair + typedef llvm::PointerIntPair SpecialMemberDecl; /// The C++ special members which we are currently in the process of @@ -5094,34 +5099,6 @@ public: /// example, in a for-range initializer). bool InLifetimeExtendingContext = false; - /// Whether we are currently in a context in which all temporaries must be - /// materialized. - /// - /// [class.temporary]/p2: - /// The materialization of a temporary object is generally delayed as long - /// as possible in order to avoid creating unnecessary temporary objects. - /// - /// Temporary objects are materialized: - /// (2.1) when binding a reference to a prvalue ([dcl.init.ref], - /// [expr.type.conv], [expr.dynamic.cast], [expr.static.cast], - /// [expr.const.cast], [expr.cast]), - /// - /// (2.2) when performing member access on a class prvalue ([expr.ref], - /// [expr.mptr.oper]), - /// - /// (2.3) when performing an array-to-pointer conversion or subscripting - /// on an array prvalue ([conv.array], [expr.sub]), - /// - /// (2.4) when initializing an object of type - /// std​::​initializer_list from a braced-init-list - /// ([dcl.init.list]), - /// - /// (2.5) for certain unevaluated operands ([expr.typeid], [expr.sizeof]) - /// - /// (2.6) when a prvalue that has type other than cv void appears as a - /// discarded-value expression ([expr.context]). - bool InMaterializeTemporaryObjectContext = false; - // When evaluating immediate functions in the initializer of a default // argument or default member initializer, this is the declaration whose // default initializer is being evaluated and the location of the call @@ -5447,8 +5424,7 @@ public: ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, - bool AcceptInvalidDecl = false, - bool NeedUnresolved = false); + bool AcceptInvalidDecl = false); ExprResult BuildDeclarationNameExpr( const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D, NamedDecl *FoundD = nullptr, @@ -6394,19 +6370,6 @@ public: } } - /// keepInMaterializeTemporaryObjectContext - Pull down - /// InMaterializeTemporaryObjectContext flag from previous context. - void keepInMaterializeTemporaryObjectContext() { - if (ExprEvalContexts.size() > 2 && - ExprEvalContexts[ExprEvalContexts.size() - 2] - .InMaterializeTemporaryObjectContext) { - auto &LastRecord = ExprEvalContexts.back(); - auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2]; - LastRecord.InMaterializeTemporaryObjectContext = - PrevRecord.InMaterializeTemporaryObjectContext; - } - } - DefaultedComparisonKind getDefaultedComparisonKind(const FunctionDecl *FD) { return getDefaultedFunctionKind(FD).asComparison(); } @@ -6550,12 +6513,6 @@ public: /// used in initializer of the field. llvm::MapVector DeleteExprs; - bool isInMaterializeTemporaryObjectContext() const { - assert(!ExprEvalContexts.empty() && - "Must be in an expression evaluation context"); - return ExprEvalContexts.back().InMaterializeTemporaryObjectContext; - } - ParsedType getInheritingConstructorName(CXXScopeSpec &SS, SourceLocation NameLoc, const IdentifierInfo &Name); @@ -6591,10 +6548,7 @@ public: SourceLocation RParenLoc); //// ActOnCXXThis - Parse 'this' pointer. - ExprResult ActOnCXXThis(SourceLocation Loc); - - /// Check whether the type of 'this' is valid in the current context. - bool CheckCXXThisType(SourceLocation Loc, QualType Type); + ExprResult ActOnCXXThis(SourceLocation loc); /// Build a CXXThisExpr and mark it referenced in the current context. Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit); @@ -7017,14 +6971,10 @@ private: ///@{ public: - /// Check whether an expression might be an implicit class member access. - bool isPotentialImplicitMemberAccess(const CXXScopeSpec &SS, LookupResult &R, - bool IsAddressOfOperand); - ExprResult BuildPossibleImplicitMemberExpr( const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs, const Scope *S); - + const TemplateArgumentListInfo *TemplateArgs, const Scope *S, + UnresolvedLookupExpr *AsULE = nullptr); ExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, @@ -7508,7 +7458,7 @@ public: }; SpecialMemberOverloadResult - LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMember SM, bool ConstArg, + LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMemberKind SM, bool ConstArg, bool VolatileArg, bool RValueThis, bool ConstThis, bool VolatileThis); @@ -8094,6 +8044,11 @@ public: bool IsFunctionConversion(QualType FromType, QualType ToType, QualType &ResultTy); bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType); + void DiagnoseUseOfDeletedFunction(SourceLocation Loc, SourceRange Range, + DeclarationName Name, + OverloadCandidateSet &CandidateSet, + FunctionDecl *Fn, MultiExprArg Args, + bool IsMember = false); ExprResult InitializeExplicitObjectArgument(Sema &S, Expr *Obj, FunctionDecl *Fun); @@ -10029,7 +9984,7 @@ public: unsigned NumCallArgs; /// The special member being declared or defined. - CXXSpecialMember SpecialMember; + CXXSpecialMemberKind SpecialMember; }; ArrayRef template_arguments() const { @@ -12915,257 +12870,6 @@ private: // // - /// \name CUDA - /// Implementations are in SemaCUDA.cpp - ///@{ - -public: - /// Increments our count of the number of times we've seen a pragma forcing - /// functions to be __host__ __device__. So long as this count is greater - /// than zero, all functions encountered will be __host__ __device__. - void PushForceCUDAHostDevice(); - - /// Decrements our count of the number of times we've seen a pragma forcing - /// functions to be __host__ __device__. Returns false if the count is 0 - /// before incrementing, so you can emit an error. - bool PopForceCUDAHostDevice(); - - ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, - MultiExprArg ExecConfig, - SourceLocation GGGLoc); - - /// Diagnostics that are emitted only if we discover that the given function - /// must be codegen'ed. Because handling these correctly adds overhead to - /// compilation, this is currently only enabled for CUDA compilations. - SemaDiagnosticBuilder::DeferredDiagnosticsType DeviceDeferredDiags; - - /// A pair of a canonical FunctionDecl and a SourceLocation. When used as the - /// key in a hashtable, both the FD and location are hashed. - struct FunctionDeclAndLoc { - CanonicalDeclPtr FD; - SourceLocation Loc; - }; - - /// FunctionDecls and SourceLocations for which CheckCUDACall has emitted a - /// (maybe deferred) "bad call" diagnostic. We use this to avoid emitting the - /// same deferred diag twice. - llvm::DenseSet LocsWithCUDACallDiags; - - /// An inverse call graph, mapping known-emitted functions to one of their - /// known-emitted callers (plus the location of the call). - /// - /// Functions that we can tell a priori must be emitted aren't added to this - /// map. - llvm::DenseMap, - /* Caller = */ FunctionDeclAndLoc> - DeviceKnownEmittedFns; - - /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current - /// context is "used as device code". - /// - /// - If CurContext is a __host__ function, does not emit any diagnostics - /// unless \p EmitOnBothSides is true. - /// - If CurContext is a __device__ or __global__ function, emits the - /// diagnostics immediately. - /// - If CurContext is a __host__ __device__ function and we are compiling for - /// the device, creates a diagnostic which is emitted if and when we realize - /// that the function will be codegen'ed. - /// - /// Example usage: - /// - /// // Variable-length arrays are not allowed in CUDA device code. - /// if (CUDADiagIfDeviceCode(Loc, diag::err_cuda_vla) << CurrentCUDATarget()) - /// return ExprError(); - /// // Otherwise, continue parsing as normal. - SemaDiagnosticBuilder CUDADiagIfDeviceCode(SourceLocation Loc, - unsigned DiagID); - - /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current - /// context is "used as host code". - /// - /// Same as CUDADiagIfDeviceCode, with "host" and "device" switched. - SemaDiagnosticBuilder CUDADiagIfHostCode(SourceLocation Loc, unsigned DiagID); - - /// Determines whether the given function is a CUDA device/host/kernel/etc. - /// function. - /// - /// Use this rather than examining the function's attributes yourself -- you - /// will get it wrong. Returns CFT_Host if D is null. - CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D, - bool IgnoreImplicitHDAttr = false); - CUDAFunctionTarget IdentifyCUDATarget(const ParsedAttributesView &Attrs); - - enum CUDAVariableTarget { - CVT_Device, /// Emitted on device side with a shadow variable on host side - CVT_Host, /// Emitted on host side only - CVT_Both, /// Emitted on both sides with different addresses - CVT_Unified, /// Emitted as a unified address, e.g. managed variables - }; - /// Determines whether the given variable is emitted on host or device side. - CUDAVariableTarget IdentifyCUDATarget(const VarDecl *D); - - /// Defines kinds of CUDA global host/device context where a function may be - /// called. - enum CUDATargetContextKind { - CTCK_Unknown, /// Unknown context - CTCK_InitGlobalVar, /// Function called during global variable - /// initialization - }; - - /// Define the current global CUDA host/device context where a function may be - /// called. Only used when a function is called outside of any functions. - struct CUDATargetContext { - CUDAFunctionTarget Target = CFT_HostDevice; - CUDATargetContextKind Kind = CTCK_Unknown; - Decl *D = nullptr; - } CurCUDATargetCtx; - - struct CUDATargetContextRAII { - Sema &S; - CUDATargetContext SavedCtx; - CUDATargetContextRAII(Sema &S_, CUDATargetContextKind K, Decl *D); - ~CUDATargetContextRAII() { S.CurCUDATargetCtx = SavedCtx; } - }; - - /// Gets the CUDA target for the current context. - CUDAFunctionTarget CurrentCUDATarget() { - return IdentifyCUDATarget(dyn_cast(CurContext)); - } - - static bool isCUDAImplicitHostDeviceFunction(const FunctionDecl *D); - - // CUDA function call preference. Must be ordered numerically from - // worst to best. - enum CUDAFunctionPreference { - CFP_Never, // Invalid caller/callee combination. - CFP_WrongSide, // Calls from host-device to host or device - // function that do not match current compilation - // mode. - CFP_HostDevice, // Any calls to host/device functions. - CFP_SameSide, // Calls from host-device to host or device - // function matching current compilation mode. - CFP_Native, // host-to-host or device-to-device calls. - }; - - /// Identifies relative preference of a given Caller/Callee - /// combination, based on their host/device attributes. - /// \param Caller function which needs address of \p Callee. - /// nullptr in case of global context. - /// \param Callee target function - /// - /// \returns preference value for particular Caller/Callee combination. - CUDAFunctionPreference IdentifyCUDAPreference(const FunctionDecl *Caller, - const FunctionDecl *Callee); - - /// Determines whether Caller may invoke Callee, based on their CUDA - /// host/device attributes. Returns false if the call is not allowed. - /// - /// Note: Will return true for CFP_WrongSide calls. These may appear in - /// semantically correct CUDA programs, but only if they're never codegen'ed. - bool IsAllowedCUDACall(const FunctionDecl *Caller, - const FunctionDecl *Callee) { - return IdentifyCUDAPreference(Caller, Callee) != CFP_Never; - } - - /// May add implicit CUDAHostAttr and CUDADeviceAttr attributes to FD, - /// depending on FD and the current compilation settings. - void maybeAddCUDAHostDeviceAttrs(FunctionDecl *FD, - const LookupResult &Previous); - - /// May add implicit CUDAConstantAttr attribute to VD, depending on VD - /// and current compilation settings. - void MaybeAddCUDAConstantAttr(VarDecl *VD); - - /// Check whether we're allowed to call Callee from the current context. - /// - /// - If the call is never allowed in a semantically-correct program - /// (CFP_Never), emits an error and returns false. - /// - /// - If the call is allowed in semantically-correct programs, but only if - /// it's never codegen'ed (CFP_WrongSide), creates a deferred diagnostic to - /// be emitted if and when the caller is codegen'ed, and returns true. - /// - /// Will only create deferred diagnostics for a given SourceLocation once, - /// so you can safely call this multiple times without generating duplicate - /// deferred errors. - /// - /// - Otherwise, returns true without emitting any diagnostics. - bool CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee); - - void CUDACheckLambdaCapture(CXXMethodDecl *D, const sema::Capture &Capture); - - /// Set __device__ or __host__ __device__ attributes on the given lambda - /// operator() method. - /// - /// CUDA lambdas by default is host device function unless it has explicit - /// host or device attribute. - void CUDASetLambdaAttrs(CXXMethodDecl *Method); - - /// Record \p FD if it is a CUDA/HIP implicit host device function used on - /// device side in device compilation. - void CUDARecordImplicitHostDeviceFuncUsedByDevice(const FunctionDecl *FD); - - /// Finds a function in \p Matches with highest calling priority - /// from \p Caller context and erases all functions with lower - /// calling priority. - void EraseUnwantedCUDAMatches( - const FunctionDecl *Caller, - SmallVectorImpl> &Matches); - - /// Given a implicit special member, infer its CUDA target from the - /// calls it needs to make to underlying base/field special members. - /// \param ClassDecl the class for which the member is being created. - /// \param CSM the kind of special member. - /// \param MemberDecl the special member itself. - /// \param ConstRHS true if this is a copy operation with a const object on - /// its RHS. - /// \param Diagnose true if this call should emit diagnostics. - /// \return true if there was an error inferring. - /// The result of this call is implicit CUDA target attribute(s) attached to - /// the member declaration. - bool inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, - CXXSpecialMember CSM, - CXXMethodDecl *MemberDecl, - bool ConstRHS, bool Diagnose); - - /// \return true if \p CD can be considered empty according to CUDA - /// (E.2.3.1 in CUDA 7.5 Programming guide). - bool isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD); - bool isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *CD); - - // \brief Checks that initializers of \p Var satisfy CUDA restrictions. In - // case of error emits appropriate diagnostic and invalidates \p Var. - // - // \details CUDA allows only empty constructors as initializers for global - // variables (see E.2.3.1, CUDA 7.5). The same restriction also applies to all - // __shared__ variables whether they are local or not (they all are implicitly - // static in CUDA). One exception is that CUDA allows constant initializers - // for __constant__ and __device__ variables. - void checkAllowedCUDAInitializer(VarDecl *VD); - - /// Check whether NewFD is a valid overload for CUDA. Emits - /// diagnostics and invalidates NewFD if not. - void checkCUDATargetOverload(FunctionDecl *NewFD, - const LookupResult &Previous); - /// Copies target attributes from the template TD to the function FD. - void inheritCUDATargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD); - - /// Returns the name of the launch configuration function. This is the name - /// of the function that will be called to configure kernel call, with the - /// parameters specified via <<<>>>. - std::string getCudaConfigureFuncName() const; - -private: - unsigned ForceCUDAHostDeviceDepth = 0; - - ///@} - - // - // - // ------------------------------------------------------------------------- - // - // - /// \name OpenMP Directives and Clauses /// Implementations are in SemaOpenMP.cpp ///@{ @@ -14552,32 +14256,4 @@ std::unique_ptr CreateRISCVIntrinsicManager(Sema &S); } // end namespace clang -namespace llvm { -// Hash a FunctionDeclAndLoc by looking at both its FunctionDecl and its -// SourceLocation. -template <> struct DenseMapInfo { - using FunctionDeclAndLoc = clang::Sema::FunctionDeclAndLoc; - using FDBaseInfo = - DenseMapInfo>; - - static FunctionDeclAndLoc getEmptyKey() { - return {FDBaseInfo::getEmptyKey(), clang::SourceLocation()}; - } - - static FunctionDeclAndLoc getTombstoneKey() { - return {FDBaseInfo::getTombstoneKey(), clang::SourceLocation()}; - } - - static unsigned getHashValue(const FunctionDeclAndLoc &FDL) { - return hash_combine(FDBaseInfo::getHashValue(FDL.FD), - FDL.Loc.getHashValue()); - } - - static bool isEqual(const FunctionDeclAndLoc &LHS, - const FunctionDeclAndLoc &RHS) { - return LHS.FD == RHS.FD && LHS.Loc == RHS.Loc; - } -}; -} // namespace llvm - #endif diff --git a/clang/include/clang/Sema/SemaBase.h b/clang/include/clang/Sema/SemaBase.h index ff718022fca03cbc91c2efb79b02c21aceafd626..3220f71dd797ed0a125a666a17ee85150e57c283 100644 --- a/clang/include/clang/Sema/SemaBase.h +++ b/clang/include/clang/Sema/SemaBase.h @@ -146,7 +146,7 @@ public: /// if (SemaDiagnosticBuilder(...) << foo << bar) /// return ExprError(); /// - /// But see CUDADiagIfDeviceCode() and CUDADiagIfHostCode() -- you probably + /// But see DiagIfDeviceCode() and DiagIfHostCode() -- you probably /// want to use these instead of creating a SemaDiagnosticBuilder yourself. operator bool() const { return isImmediate(); } diff --git a/clang/include/clang/Sema/SemaCUDA.h b/clang/include/clang/Sema/SemaCUDA.h new file mode 100644 index 0000000000000000000000000000000000000000..63dc3f4da240b365cc51325b6d0fe7899d62f13c --- /dev/null +++ b/clang/include/clang/Sema/SemaCUDA.h @@ -0,0 +1,304 @@ +//===----- SemaCUDA.h ----- Semantic Analysis for CUDA constructs ---------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// \file +/// This file declares semantic analysis for CUDA constructs. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_SEMACUDA_H +#define LLVM_CLANG_SEMA_SEMACUDA_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Redeclarable.h" +#include "clang/Basic/Cuda.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Ownership.h" +#include "clang/Sema/ParsedAttr.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaBase.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include + +namespace clang { + +enum class CUDAFunctionTarget; + +class SemaCUDA : public SemaBase { +public: + SemaCUDA(Sema &S); + + /// Increments our count of the number of times we've seen a pragma forcing + /// functions to be __host__ __device__. So long as this count is greater + /// than zero, all functions encountered will be __host__ __device__. + void PushForceHostDevice(); + + /// Decrements our count of the number of times we've seen a pragma forcing + /// functions to be __host__ __device__. Returns false if the count is 0 + /// before incrementing, so you can emit an error. + bool PopForceHostDevice(); + + ExprResult ActOnExecConfigExpr(Scope *S, SourceLocation LLLLoc, + MultiExprArg ExecConfig, + SourceLocation GGGLoc); + + /// A pair of a canonical FunctionDecl and a SourceLocation. When used as the + /// key in a hashtable, both the FD and location are hashed. + struct FunctionDeclAndLoc { + CanonicalDeclPtr FD; + SourceLocation Loc; + }; + + /// FunctionDecls and SourceLocations for which CheckCall has emitted a + /// (maybe deferred) "bad call" diagnostic. We use this to avoid emitting the + /// same deferred diag twice. + llvm::DenseSet LocsWithCUDACallDiags; + + /// An inverse call graph, mapping known-emitted functions to one of their + /// known-emitted callers (plus the location of the call). + /// + /// Functions that we can tell a priori must be emitted aren't added to this + /// map. + llvm::DenseMap, + /* Caller = */ FunctionDeclAndLoc> + DeviceKnownEmittedFns; + + /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current + /// context is "used as device code". + /// + /// - If CurContext is a __host__ function, does not emit any diagnostics + /// unless \p EmitOnBothSides is true. + /// - If CurContext is a __device__ or __global__ function, emits the + /// diagnostics immediately. + /// - If CurContext is a __host__ __device__ function and we are compiling for + /// the device, creates a diagnostic which is emitted if and when we realize + /// that the function will be codegen'ed. + /// + /// Example usage: + /// + /// // Variable-length arrays are not allowed in CUDA device code. + /// if (DiagIfDeviceCode(Loc, diag::err_cuda_vla) << CurrentTarget()) + /// return ExprError(); + /// // Otherwise, continue parsing as normal. + SemaDiagnosticBuilder DiagIfDeviceCode(SourceLocation Loc, unsigned DiagID); + + /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current + /// context is "used as host code". + /// + /// Same as DiagIfDeviceCode, with "host" and "device" switched. + SemaDiagnosticBuilder DiagIfHostCode(SourceLocation Loc, unsigned DiagID); + + /// Determines whether the given function is a CUDA device/host/kernel/etc. + /// function. + /// + /// Use this rather than examining the function's attributes yourself -- you + /// will get it wrong. Returns CUDAFunctionTarget::Host if D is null. + CUDAFunctionTarget IdentifyTarget(const FunctionDecl *D, + bool IgnoreImplicitHDAttr = false); + CUDAFunctionTarget IdentifyTarget(const ParsedAttributesView &Attrs); + + enum CUDAVariableTarget { + CVT_Device, /// Emitted on device side with a shadow variable on host side + CVT_Host, /// Emitted on host side only + CVT_Both, /// Emitted on both sides with different addresses + CVT_Unified, /// Emitted as a unified address, e.g. managed variables + }; + /// Determines whether the given variable is emitted on host or device side. + CUDAVariableTarget IdentifyTarget(const VarDecl *D); + + /// Defines kinds of CUDA global host/device context where a function may be + /// called. + enum CUDATargetContextKind { + CTCK_Unknown, /// Unknown context + CTCK_InitGlobalVar, /// Function called during global variable + /// initialization + }; + + /// Define the current global CUDA host/device context where a function may be + /// called. Only used when a function is called outside of any functions. + struct CUDATargetContext { + CUDAFunctionTarget Target = CUDAFunctionTarget::HostDevice; + CUDATargetContextKind Kind = CTCK_Unknown; + Decl *D = nullptr; + } CurCUDATargetCtx; + + struct CUDATargetContextRAII { + SemaCUDA &S; + SemaCUDA::CUDATargetContext SavedCtx; + CUDATargetContextRAII(SemaCUDA &S_, SemaCUDA::CUDATargetContextKind K, + Decl *D); + ~CUDATargetContextRAII() { S.CurCUDATargetCtx = SavedCtx; } + }; + + /// Gets the CUDA target for the current context. + CUDAFunctionTarget CurrentTarget() { + return IdentifyTarget(dyn_cast(SemaRef.CurContext)); + } + + static bool isImplicitHostDeviceFunction(const FunctionDecl *D); + + // CUDA function call preference. Must be ordered numerically from + // worst to best. + enum CUDAFunctionPreference { + CFP_Never, // Invalid caller/callee combination. + CFP_WrongSide, // Calls from host-device to host or device + // function that do not match current compilation + // mode. + CFP_HostDevice, // Any calls to host/device functions. + CFP_SameSide, // Calls from host-device to host or device + // function matching current compilation mode. + CFP_Native, // host-to-host or device-to-device calls. + }; + + /// Identifies relative preference of a given Caller/Callee + /// combination, based on their host/device attributes. + /// \param Caller function which needs address of \p Callee. + /// nullptr in case of global context. + /// \param Callee target function + /// + /// \returns preference value for particular Caller/Callee combination. + CUDAFunctionPreference IdentifyPreference(const FunctionDecl *Caller, + const FunctionDecl *Callee); + + /// Determines whether Caller may invoke Callee, based on their CUDA + /// host/device attributes. Returns false if the call is not allowed. + /// + /// Note: Will return true for CFP_WrongSide calls. These may appear in + /// semantically correct CUDA programs, but only if they're never codegen'ed. + bool IsAllowedCall(const FunctionDecl *Caller, const FunctionDecl *Callee) { + return IdentifyPreference(Caller, Callee) != CFP_Never; + } + + /// May add implicit CUDAHostAttr and CUDADeviceAttr attributes to FD, + /// depending on FD and the current compilation settings. + void maybeAddHostDeviceAttrs(FunctionDecl *FD, const LookupResult &Previous); + + /// May add implicit CUDAConstantAttr attribute to VD, depending on VD + /// and current compilation settings. + void MaybeAddConstantAttr(VarDecl *VD); + + /// Check whether we're allowed to call Callee from the current context. + /// + /// - If the call is never allowed in a semantically-correct program + /// (CFP_Never), emits an error and returns false. + /// + /// - If the call is allowed in semantically-correct programs, but only if + /// it's never codegen'ed (CFP_WrongSide), creates a deferred diagnostic to + /// be emitted if and when the caller is codegen'ed, and returns true. + /// + /// Will only create deferred diagnostics for a given SourceLocation once, + /// so you can safely call this multiple times without generating duplicate + /// deferred errors. + /// + /// - Otherwise, returns true without emitting any diagnostics. + bool CheckCall(SourceLocation Loc, FunctionDecl *Callee); + + void CheckLambdaCapture(CXXMethodDecl *D, const sema::Capture &Capture); + + /// Set __device__ or __host__ __device__ attributes on the given lambda + /// operator() method. + /// + /// CUDA lambdas by default is host device function unless it has explicit + /// host or device attribute. + void SetLambdaAttrs(CXXMethodDecl *Method); + + /// Record \p FD if it is a CUDA/HIP implicit host device function used on + /// device side in device compilation. + void RecordImplicitHostDeviceFuncUsedByDevice(const FunctionDecl *FD); + + /// Finds a function in \p Matches with highest calling priority + /// from \p Caller context and erases all functions with lower + /// calling priority. + void EraseUnwantedMatches( + const FunctionDecl *Caller, + llvm::SmallVectorImpl> + &Matches); + + /// Given a implicit special member, infer its CUDA target from the + /// calls it needs to make to underlying base/field special members. + /// \param ClassDecl the class for which the member is being created. + /// \param CSM the kind of special member. + /// \param MemberDecl the special member itself. + /// \param ConstRHS true if this is a copy operation with a const object on + /// its RHS. + /// \param Diagnose true if this call should emit diagnostics. + /// \return true if there was an error inferring. + /// The result of this call is implicit CUDA target attribute(s) attached to + /// the member declaration. + bool inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, + CXXSpecialMemberKind CSM, + CXXMethodDecl *MemberDecl, + bool ConstRHS, bool Diagnose); + + /// \return true if \p CD can be considered empty according to CUDA + /// (E.2.3.1 in CUDA 7.5 Programming guide). + bool isEmptyConstructor(SourceLocation Loc, CXXConstructorDecl *CD); + bool isEmptyDestructor(SourceLocation Loc, CXXDestructorDecl *CD); + + // \brief Checks that initializers of \p Var satisfy CUDA restrictions. In + // case of error emits appropriate diagnostic and invalidates \p Var. + // + // \details CUDA allows only empty constructors as initializers for global + // variables (see E.2.3.1, CUDA 7.5). The same restriction also applies to all + // __shared__ variables whether they are local or not (they all are implicitly + // static in CUDA). One exception is that CUDA allows constant initializers + // for __constant__ and __device__ variables. + void checkAllowedInitializer(VarDecl *VD); + + /// Check whether NewFD is a valid overload for CUDA. Emits + /// diagnostics and invalidates NewFD if not. + void checkTargetOverload(FunctionDecl *NewFD, const LookupResult &Previous); + /// Copies target attributes from the template TD to the function FD. + void inheritTargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD); + + /// Returns the name of the launch configuration function. This is the name + /// of the function that will be called to configure kernel call, with the + /// parameters specified via <<<>>>. + std::string getConfigureFuncName() const; + +private: + unsigned ForceHostDeviceDepth = 0; + + friend class ASTReader; + friend class ASTWriter; +}; + +} // namespace clang + +namespace llvm { +// Hash a FunctionDeclAndLoc by looking at both its FunctionDecl and its +// SourceLocation. +template <> struct DenseMapInfo { + using FunctionDeclAndLoc = clang::SemaCUDA::FunctionDeclAndLoc; + using FDBaseInfo = + DenseMapInfo>; + + static FunctionDeclAndLoc getEmptyKey() { + return {FDBaseInfo::getEmptyKey(), clang::SourceLocation()}; + } + + static FunctionDeclAndLoc getTombstoneKey() { + return {FDBaseInfo::getTombstoneKey(), clang::SourceLocation()}; + } + + static unsigned getHashValue(const FunctionDeclAndLoc &FDL) { + return hash_combine(FDBaseInfo::getHashValue(FDL.FD), + FDL.Loc.getHashValue()); + } + + static bool isEqual(const FunctionDeclAndLoc &LHS, + const FunctionDeclAndLoc &RHS) { + return LHS.FD == RHS.FD && LHS.Loc == RHS.Loc; + } +}; +} // namespace llvm + +#endif // LLVM_CLANG_SEMA_SEMACUDA_H diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index acc675963c23a580c93ce0e09e3f53c6145e9234..34acaf19517f2a58be7fd54667d7b8a1a8e28ef1 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -13,12 +13,16 @@ #ifndef LLVM_CLANG_SEMA_SEMAHLSL_H #define LLVM_CLANG_SEMA_SEMAHLSL_H +#include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/Expr.h" +#include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaBase.h" +#include namespace clang { @@ -26,10 +30,25 @@ class SemaHLSL : public SemaBase { public: SemaHLSL(Sema &S); - Decl *ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer, - SourceLocation KwLoc, IdentifierInfo *Ident, - SourceLocation IdentLoc, SourceLocation LBrace); - void ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace); + Decl *ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, + IdentifierInfo *Ident, SourceLocation IdentLoc, + SourceLocation LBrace); + void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace); + HLSLNumThreadsAttr *mergeNumThreadsAttr(Decl *D, + const AttributeCommonInfo &AL, int X, + int Y, int Z); + HLSLShaderAttr *mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, + HLSLShaderAttr::ShaderType ShaderType); + HLSLParamModifierAttr * + mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, + HLSLParamModifierAttr::Spelling Spelling); + void ActOnTopLevelFunction(FunctionDecl *FD); + void CheckEntryPoint(FunctionDecl *FD); + void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, + const HLSLAnnotationAttr *AnnotationAttr); + void DiagnoseAttrStageMismatch( + const Attr *A, HLSLShaderAttr::ShaderType Stage, + std::initializer_list AllowedStages); }; } // namespace clang diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index 27aaee164a28809d585152b5c47c89c3a919d052..c1fe0f5b9c0f6bdad1d83d49cb4cc85ae49722c9 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -40,7 +40,11 @@ public: OpenACCDefaultClauseKind DefaultClauseKind; }; - std::variant Details; + struct ConditionDetails { + Expr *ConditionExpr; + }; + + std::variant Details; public: OpenACCParsedClause(OpenACCDirectiveKind DirKind, @@ -63,6 +67,16 @@ public: return std::get(Details).DefaultClauseKind; } + const Expr *getConditionExpr() const { + return const_cast(this)->getConditionExpr(); + } + + Expr *getConditionExpr() { + assert(ClauseKind == OpenACCClauseKind::If && + "Parsed clause kind does not have a condition expr"); + return std::get(Details).ConditionExpr; + } + void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; } void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); } @@ -71,6 +85,18 @@ public: "Parsed clause is not a default clause"); Details = DefaultDetails{DefKind}; } + + void setConditionDetails(Expr *ConditionExpr) { + assert(ClauseKind == OpenACCClauseKind::If && + "Parsed clause kind does not have a condition expr"); + // In C++ we can count on this being a 'bool', but in C this gets left as + // some sort of scalar that codegen will have to take care of converting. + assert((!ConditionExpr || ConditionExpr->isInstantiationDependent() || + ConditionExpr->getType()->isScalarType()) && + "Condition expression type not scalar/dependent"); + + Details = ConditionDetails{ConditionExpr}; + } }; SemaOpenACC(Sema &S); diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index f762116fea956c3fbee92038538e0f3e81f06c7e..500098dd3dab1d25e49cb350e67b2e5ce1ad104b 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -698,6 +698,10 @@ enum ASTRecordTypes { /// Record code for an unterminated \#pragma clang assume_nonnull begin /// recorded in a preamble. PP_ASSUME_NONNULL_LOC = 67, + + /// Record code for lexical and visible block for delayed namespace in + /// reduced BMI. + DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD = 68, }; /// Record types used within a source manager block. diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index e8b9f28690d9fa06ab536f45c6be52b50fbcdca4..e3fde887f99cb743b096fef6bc4b04bc3da07b54 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -517,6 +517,20 @@ private: /// in the chain. DeclUpdateOffsetsMap DeclUpdateOffsets; + using DelayedNamespaceOffsetMapTy = llvm::DenseMap< + serialization::DeclID, + std::pair>; + + /// Mapping from global declaration IDs to the lexical and visible block + /// offset for delayed namespace in reduced BMI. + /// + /// We can't use the existing DeclUpdate mechanism since the DeclUpdate + /// may only be applied in an outer most read. However, we need to know + /// whether or not a DeclContext has external storage during the recursive + /// reading. So we need to apply the offset immediately after we read the + /// namespace as if it is not delayed. + DelayedNamespaceOffsetMapTy DelayedNamespaceOffsetMap; + struct PendingUpdateRecord { Decl *D; serialization::GlobalDeclID ID; @@ -859,7 +873,7 @@ private: /// Our current depth in #pragma cuda force_host_device begin/end /// macros. - unsigned ForceCUDAHostDeviceDepth = 0; + unsigned ForceHostDeviceDepth = 0; /// The IDs of the declarations Sema stores directly. /// diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 214eb3601148b0d18d6392d535e23e7d5d3baffd..443f77031047006df8108f26570a669f30fc5c75 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -201,6 +201,16 @@ private: /// The declarations and types to emit. std::queue DeclTypesToEmit; + /// The delayed namespace to emit. Only meaningful for reduced BMI. + /// + /// In reduced BMI, we want to elide the unreachable declarations in + /// the global module fragment. However, in ASTWriterDecl, when we see + /// a namespace, all the declarations in the namespace would be emitted. + /// So the optimization become meaningless. To solve the issue, we + /// delay recording all the declarations until we emit all the declarations. + /// Then we can safely record the reached declarations only. + llvm::SmallVector DelayedNamespace; + /// The first ID number we can use for our own declarations. serialization::DeclID FirstDeclID = serialization::NUM_PREDEF_DECL_IDS; @@ -529,7 +539,8 @@ private: void WriteType(QualType T); bool isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC); - bool isLookupResultEntirelyExternal(StoredDeclsList &Result, DeclContext *DC); + bool isLookupResultEntirelyExternalOrUnreachable(StoredDeclsList &Result, + DeclContext *DC); void GenerateNameLookupTable(const DeclContext *DC, llvm::SmallVectorImpl &LookupTable); @@ -704,6 +715,15 @@ public: /// declaration. serialization::DeclID getDeclID(const Decl *D); + /// Whether or not the declaration got emitted. If not, it wouldn't be + /// emitted. + /// + /// This may only be called after we've done the job to write the + /// declarations (marked by DoneWritingDeclsAndTypes). + /// + /// A declaration may only be omitted in reduced BMI. + bool wasDeclEmitted(const Decl *D) const; + unsigned getAnonymousDeclarationNumber(const NamedDecl *D); /// Add a string to the given record. @@ -798,6 +818,10 @@ public: return WritingModule && WritingModule->isNamedModule(); } + bool isGeneratingReducedBMI() const { return GeneratingReducedBMI; } + + bool getDoneWritingDeclsAndTypes() const { return DoneWritingDeclsAndTypes; } + private: // ASTDeserializationListener implementation void ReaderInitialized(ASTReader *Reader) override; diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h index 9a522a3e2fe252082e1b2ee5b839c3d1d519cb63..f7b4510d7f7beb4b6e300180453385e1a84e6af4 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -142,6 +142,8 @@ private: CachedFileContents *Contents; }; +using CachedRealPath = llvm::ErrorOr; + /// This class is a shared cache, that caches the 'stat' and 'open' calls to the /// underlying real file system, and the scanned preprocessor directives of /// files. @@ -154,9 +156,11 @@ public: /// The mutex that needs to be locked before mutation of any member. mutable std::mutex CacheLock; - /// Map from filenames to cached entries. - llvm::StringMap - EntriesByFilename; + /// Map from filenames to cached entries and real paths. + llvm::StringMap< + std::pair, + llvm::BumpPtrAllocator> + CacheByFilename; /// Map from unique IDs to cached entries. llvm::DenseMap @@ -168,6 +172,9 @@ public: /// The backing storage for cached contents. llvm::SpecificBumpPtrAllocator ContentsStorage; + /// The backing storage for cached real paths. + llvm::SpecificBumpPtrAllocator RealPathStorage; + /// Returns entry associated with the filename or nullptr if none is found. const CachedFileSystemEntry *findEntryByFilename(StringRef Filename) const; @@ -194,6 +201,17 @@ public: const CachedFileSystemEntry & getOrInsertEntryForFilename(StringRef Filename, const CachedFileSystemEntry &Entry); + + /// Returns the real path associated with the filename or nullptr if none is + /// found. + const CachedRealPath *findRealPathByFilename(StringRef Filename) const; + + /// Returns the real path associated with the filename if there is some. + /// Otherwise, constructs new one with the given one, associates it with the + /// filename and returns the result. + const CachedRealPath & + getOrEmplaceRealPathForFilename(StringRef Filename, + llvm::ErrorOr RealPath); }; DependencyScanningFilesystemSharedCache(); @@ -210,14 +228,17 @@ private: /// This class is a local cache, that caches the 'stat' and 'open' calls to the /// underlying real file system. class DependencyScanningFilesystemLocalCache { - llvm::StringMap Cache; + llvm::StringMap< + std::pair, + llvm::BumpPtrAllocator> + Cache; public: /// Returns entry associated with the filename or nullptr if none is found. const CachedFileSystemEntry *findEntryByFilename(StringRef Filename) const { assert(llvm::sys::path::is_absolute_gnu(Filename)); auto It = Cache.find(Filename); - return It == Cache.end() ? nullptr : It->getValue(); + return It == Cache.end() ? nullptr : It->getValue().first; } /// Associates the given entry with the filename and returns the given entry @@ -226,9 +247,40 @@ public: insertEntryForFilename(StringRef Filename, const CachedFileSystemEntry &Entry) { assert(llvm::sys::path::is_absolute_gnu(Filename)); - const auto *InsertedEntry = Cache.insert({Filename, &Entry}).first->second; - assert(InsertedEntry == &Entry && "entry already present"); - return *InsertedEntry; + auto [It, Inserted] = Cache.insert({Filename, {&Entry, nullptr}}); + auto &[CachedEntry, CachedRealPath] = It->getValue(); + if (!Inserted) { + // The file is already present in the local cache. If we got here, it only + // contains the real path. Let's make sure the entry is populated too. + assert((!CachedEntry && CachedRealPath) && "entry already present"); + CachedEntry = &Entry; + } + return *CachedEntry; + } + + /// Returns real path associated with the filename or nullptr if none is + /// found. + const CachedRealPath *findRealPathByFilename(StringRef Filename) const { + assert(llvm::sys::path::is_absolute_gnu(Filename)); + auto It = Cache.find(Filename); + return It == Cache.end() ? nullptr : It->getValue().second; + } + + /// Associates the given real path with the filename and returns the given + /// entry pointer (for convenience). + const CachedRealPath & + insertRealPathForFilename(StringRef Filename, + const CachedRealPath &RealPath) { + assert(llvm::sys::path::is_absolute_gnu(Filename)); + auto [It, Inserted] = Cache.insert({Filename, {nullptr, &RealPath}}); + auto &[CachedEntry, CachedRealPath] = It->getValue(); + if (!Inserted) { + // The file is already present in the local cache. If we got here, it only + // contains the entry. Let's make sure the real path is populated too. + assert((!CachedRealPath && CachedEntry) && "real path already present"); + CachedRealPath = &RealPath; + } + return *CachedRealPath; } }; @@ -296,6 +348,9 @@ public: llvm::ErrorOr> openFileForRead(const Twine &Path) override; + std::error_code getRealPath(const Twine &Path, + SmallVectorImpl &Output) override; + std::error_code setCurrentWorkingDirectory(const Twine &Path) override; /// Returns entry for the given filename. @@ -310,6 +365,10 @@ public: /// false if not (i.e. this entry is not a file or its scan fails). bool ensureDirectiveTokensArePopulated(EntryRef Entry); + /// Check whether \p Path exists. By default checks cached result of \c + /// status(), and falls back on FS if unable to do so. + bool exists(const Twine &Path) override; + private: /// For a filename that's not yet associated with any entry in the caches, /// uses the underlying filesystem to either look up the entry based in the @@ -402,6 +461,10 @@ private: llvm::ErrorOr WorkingDirForCacheLookup; void updateWorkingDirForCacheLookup(); + + llvm::ErrorOr + tryGetFilenameForLookup(StringRef OriginalFilename, + llvm::SmallVectorImpl &PathBuf) const; }; } // end namespace dependencies diff --git a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h index 081899cc2c85039a82ccf9b0756f4f4170084135..da51292296a90fa0ee9bec7daac0b320c49061b6 100644 --- a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h +++ b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h @@ -308,6 +308,11 @@ private: ModuleDeps &Deps); }; +/// Resets codegen options that don't affect modules/PCH. +void resetBenignCodeGenOptions(frontend::ActionKind ProgramAction, + const LangOptions &LangOpts, + CodeGenOptions &CGOpts); + } // end namespace dependencies } // end namespace tooling } // end namespace clang diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index a5e43fc63166759bb60dd84ab5d8196ac8521193..6aaa34c55ce3078510f4210edcc4fa11259c2739 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -3947,6 +3947,14 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // decl and its redeclarations may be required. } + StringLiteral *Msg = D->getDeletedMessage(); + if (Msg) { + auto Imported = import(Msg); + if (!Imported) + return Imported.takeError(); + Msg = *Imported; + } + ToFunction->setQualifierInfo(ToQualifierLoc); ToFunction->setAccess(D->getAccess()); ToFunction->setLexicalDeclContext(LexicalDC); @@ -3961,6 +3969,11 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction->setRangeEnd(ToEndLoc); ToFunction->setDefaultLoc(ToDefaultLoc); + if (Msg) + ToFunction->setDefaultedOrDeletedInfo( + FunctionDecl::DefaultedOrDeletedFunctionInfo::Create( + Importer.getToContext(), {}, Msg)); + // Set the parameters. for (auto *Param : Parameters) { Param->setOwningFunction(ToFunction); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 60e0a3aecf6c8e67c3cd1de634dbc92fbce4e31c..2b2d5a2663a18b41ffb551ebe896dd944d597486 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3058,7 +3058,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, FunctionDeclBits.IsTrivialForCall = false; FunctionDeclBits.IsDefaulted = false; FunctionDeclBits.IsExplicitlyDefaulted = false; - FunctionDeclBits.HasDefaultedFunctionInfo = false; + FunctionDeclBits.HasDefaultedOrDeletedInfo = false; FunctionDeclBits.IsIneligibleOrNotSelected = false; FunctionDeclBits.HasImplicitReturnZero = false; FunctionDeclBits.IsLateTemplateParsed = false; @@ -3092,30 +3092,65 @@ bool FunctionDecl::isVariadic() const { return false; } -FunctionDecl::DefaultedFunctionInfo * -FunctionDecl::DefaultedFunctionInfo::Create(ASTContext &Context, - ArrayRef Lookups) { - DefaultedFunctionInfo *Info = new (Context.Allocate( - totalSizeToAlloc(Lookups.size()), - std::max(alignof(DefaultedFunctionInfo), alignof(DeclAccessPair)))) - DefaultedFunctionInfo; +FunctionDecl::DefaultedOrDeletedFunctionInfo * +FunctionDecl::DefaultedOrDeletedFunctionInfo::Create( + ASTContext &Context, ArrayRef Lookups, + StringLiteral *DeletedMessage) { + static constexpr size_t Alignment = + std::max({alignof(DefaultedOrDeletedFunctionInfo), + alignof(DeclAccessPair), alignof(StringLiteral *)}); + size_t Size = totalSizeToAlloc( + Lookups.size(), DeletedMessage != nullptr); + + DefaultedOrDeletedFunctionInfo *Info = + new (Context.Allocate(Size, Alignment)) DefaultedOrDeletedFunctionInfo; Info->NumLookups = Lookups.size(); + Info->HasDeletedMessage = DeletedMessage != nullptr; + std::uninitialized_copy(Lookups.begin(), Lookups.end(), Info->getTrailingObjects()); + if (DeletedMessage) + *Info->getTrailingObjects() = DeletedMessage; return Info; } -void FunctionDecl::setDefaultedFunctionInfo(DefaultedFunctionInfo *Info) { - assert(!FunctionDeclBits.HasDefaultedFunctionInfo && "already have this"); +void FunctionDecl::setDefaultedOrDeletedInfo( + DefaultedOrDeletedFunctionInfo *Info) { + assert(!FunctionDeclBits.HasDefaultedOrDeletedInfo && "already have this"); assert(!Body && "can't replace function body with defaulted function info"); - FunctionDeclBits.HasDefaultedFunctionInfo = true; - DefaultedInfo = Info; + FunctionDeclBits.HasDefaultedOrDeletedInfo = true; + DefaultedOrDeletedInfo = Info; +} + +void FunctionDecl::setDeletedAsWritten(bool D, StringLiteral *Message) { + FunctionDeclBits.IsDeleted = D; + + if (Message) { + assert(isDeletedAsWritten() && "Function must be deleted"); + if (FunctionDeclBits.HasDefaultedOrDeletedInfo) + DefaultedOrDeletedInfo->setDeletedMessage(Message); + else + setDefaultedOrDeletedInfo(DefaultedOrDeletedFunctionInfo::Create( + getASTContext(), /*Lookups=*/{}, Message)); + } +} + +void FunctionDecl::DefaultedOrDeletedFunctionInfo::setDeletedMessage( + StringLiteral *Message) { + // We should never get here with the DefaultedOrDeletedInfo populated, but + // no space allocated for the deleted message, since that would require + // recreating this, but setDefaultedOrDeletedInfo() disallows overwriting + // an already existing DefaultedOrDeletedFunctionInfo. + assert(HasDeletedMessage && + "No space to store a delete message in this DefaultedOrDeletedInfo"); + *getTrailingObjects() = Message; } -FunctionDecl::DefaultedFunctionInfo * -FunctionDecl::getDefaultedFunctionInfo() const { - return FunctionDeclBits.HasDefaultedFunctionInfo ? DefaultedInfo : nullptr; +FunctionDecl::DefaultedOrDeletedFunctionInfo * +FunctionDecl::getDefalutedOrDeletedInfo() const { + return FunctionDeclBits.HasDefaultedOrDeletedInfo ? DefaultedOrDeletedInfo + : nullptr; } bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const { @@ -3202,7 +3237,7 @@ Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { if (!hasBody(Definition)) return nullptr; - assert(!Definition->FunctionDeclBits.HasDefaultedFunctionInfo && + assert(!Definition->FunctionDeclBits.HasDefaultedOrDeletedInfo && "definition should not have a body"); if (Definition->Body) return Definition->Body.get(getASTContext().getExternalSource()); @@ -3211,7 +3246,7 @@ Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { } void FunctionDecl::setBody(Stmt *B) { - FunctionDeclBits.HasDefaultedFunctionInfo = false; + FunctionDeclBits.HasDefaultedOrDeletedInfo = false; Body = LazyDeclStmtPtr(B); if (B) EndRangeLoc = B->getEndLoc(); diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index c66774dd1df1516a495b5244b63ff9b7c239a8c2..93857adb990bf209d3ccbff6e0016f2fbe0de4f8 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -822,9 +822,14 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (D->isPureVirtual()) Out << " = 0"; - else if (D->isDeletedAsWritten()) + else if (D->isDeletedAsWritten()) { Out << " = delete"; - else if (D->isExplicitlyDefaulted()) + if (const StringLiteral *M = D->getDeletedMessage()) { + Out << "("; + M->outputString(Out); + Out << ")"; + } + } else if (D->isExplicitlyDefaulted()) Out << " = default"; else if (D->doesThisDeclarationHaveABody()) { if (!Policy.TerseOutput) { diff --git a/clang/lib/AST/Interp/FunctionPointer.h b/clang/lib/AST/Interp/FunctionPointer.h index 840c1101f396b9516a6508a334bfa9985e18a8da..c2ea295b82bdf560d26b16ec2b21a87028e9ed63 100644 --- a/clang/lib/AST/Interp/FunctionPointer.h +++ b/clang/lib/AST/Interp/FunctionPointer.h @@ -32,6 +32,12 @@ public: const Function *getFunction() const { return Func; } bool isZero() const { return !Func; } + bool isWeak() const { + if (!Func || !Valid) + return false; + + return Func->getDecl()->isWeak(); + } APValue toAPValue() const { if (!Func) diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index c7012aa4ec680bed8d2b5b3bdf0d90996c84c401..4182254357eb9a4327b4458b973662f7bd789c49 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -758,7 +758,7 @@ inline bool CmpHelperEQ(InterpState &S, CodePtr OpPC, // We cannot compare against weak declarations at compile time. for (const auto &FP : {LHS, RHS}) { - if (!FP.isZero() && FP.getFunction()->getDecl()->isWeak()) { + if (FP.isWeak()) { const SourceInfo &Loc = S.Current->getSource(OpPC); S.FFDiag(Loc, diag::note_constexpr_pointer_weak_comparison) << FP.toDiagnosticString(S.getCtx()); diff --git a/clang/lib/AST/Interp/InterpState.h b/clang/lib/AST/Interp/InterpState.h index 8f84bf6ed2eaffa908c61f2f1e2ddf5930d7cde1..c17cfad11b1e2b6145c2554cb0d29c0cd208a993 100644 --- a/clang/lib/AST/Interp/InterpState.h +++ b/clang/lib/AST/Interp/InterpState.h @@ -89,7 +89,11 @@ public: /// Delegates source mapping to the mapper. SourceInfo getSource(const Function *F, CodePtr PC) const override { - return M ? M->getSource(F, PC) : F->getSource(PC); + if (M) + return M->getSource(F, PC); + + assert(F && "Function cannot be null"); + return F->getSource(PC); } Context &getContext() const { return Ctx; } diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index fb3494393f7559af8765b5c29a0634f6bdb6dfb5..42608476b1c195ca9c23bd0b91b7cfb822316857 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -975,6 +975,9 @@ void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) { if (FD->isDefaulted()) JOS.attribute("explicitlyDefaulted", FD->isDeleted() ? "deleted" : "default"); + + if (StringLiteral *Msg = FD->getDeletedMessage()) + JOS.attribute("deletedMessage", Msg->getString()); } void JSONNodeDumper::VisitEnumDecl(const EnumDecl *ED) { @@ -1576,6 +1579,14 @@ void JSONNodeDumper::VisitMaterializeTemporaryExpr( attributeOnlyIfTrue("boundToLValueRef", MTE->isBoundToLvalueReference()); } +void JSONNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) { + attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit()); +} + +void JSONNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) { + attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit()); +} + void JSONNodeDumper::VisitCXXDependentScopeMemberExpr( const CXXDependentScopeMemberExpr *DSME) { JOS.attribute("isArrow", DSME->isArrow()); diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index e159a1b00be552bab566c07313ff64264f9951ff..6f04739cf6693d612d9464075b7699624568bad9 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -696,6 +696,12 @@ void ODRHash::AddFunctionDecl(const FunctionDecl *Function, AddBoolean(Function->isDeletedAsWritten()); AddBoolean(Function->isExplicitlyDefaulted()); + StringLiteral *DeletedMessage = Function->getDeletedMessage(); + AddBoolean(DeletedMessage); + + if (DeletedMessage) + ID.AddString(DeletedMessage->getBytes()); + AddDecl(Function); AddQualType(Function->getReturnType()); diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp index c83128b60e3acc44de9386f00e591ea1d799f224..dcb512cb514179f627138eba0a4246c17604d71e 100644 --- a/clang/lib/AST/OpenACCClause.cpp +++ b/clang/lib/AST/OpenACCClause.cpp @@ -13,6 +13,7 @@ #include "clang/AST/OpenACCClause.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Expr.h" using namespace clang; @@ -27,10 +28,47 @@ OpenACCDefaultClause *OpenACCDefaultClause::Create(const ASTContext &C, return new (Mem) OpenACCDefaultClause(K, BeginLoc, LParenLoc, EndLoc); } +OpenACCIfClause *OpenACCIfClause::Create(const ASTContext &C, + SourceLocation BeginLoc, + SourceLocation LParenLoc, + Expr *ConditionExpr, + SourceLocation EndLoc) { + void *Mem = C.Allocate(sizeof(OpenACCIfClause), alignof(OpenACCIfClause)); + return new (Mem) OpenACCIfClause(BeginLoc, LParenLoc, ConditionExpr, EndLoc); +} + +OpenACCIfClause::OpenACCIfClause(SourceLocation BeginLoc, + SourceLocation LParenLoc, Expr *ConditionExpr, + SourceLocation EndLoc) + : OpenACCClauseWithCondition(OpenACCClauseKind::If, BeginLoc, LParenLoc, + ConditionExpr, EndLoc) { + assert(ConditionExpr && "if clause requires condition expr"); + assert((ConditionExpr->isInstantiationDependent() || + ConditionExpr->getType()->isScalarType()) && + "Condition expression type not scalar/dependent"); +} + +OpenACCClause::child_range OpenACCClause::children() { + switch (getClauseKind()) { + default: + assert(false && "Clause children function not implemented"); + break; +#define VISIT_CLAUSE(CLAUSE_NAME) \ + case OpenACCClauseKind::CLAUSE_NAME: \ + return cast(this)->children(); + +#include "clang/Basic/OpenACCClauses.def" + } + return child_range(child_iterator(), child_iterator()); +} + //===----------------------------------------------------------------------===// // OpenACC clauses printing methods //===----------------------------------------------------------------------===// -void OpenACCClausePrinter::VisitOpenACCDefaultClause( - const OpenACCDefaultClause &C) { +void OpenACCClausePrinter::VisitDefaultClause(const OpenACCDefaultClause &C) { OS << "default(" << C.getDefaultClauseKind() << ")"; } + +void OpenACCClausePrinter::VisitIfClause(const OpenACCIfClause &C) { + OS << "if(" << C.getConditionExpr() << ")"; +} diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 01e1d1cc8289bfdbca3b4e15e3c09a16cd926f2d..d2aac1e640380f956194b45ce1492c3f38430ec4 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2445,9 +2445,10 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { namespace { class OpenACCClauseProfiler : public OpenACCClauseVisitor { + StmtProfiler &Profiler; public: - OpenACCClauseProfiler() = default; + OpenACCClauseProfiler(StmtProfiler &P) : Profiler(P) {} void VisitOpenACCClauseList(ArrayRef Clauses) { for (const OpenACCClause *Clause : Clauses) { @@ -2456,12 +2457,22 @@ public: Visit(Clause); } } - void VisitOpenACCDefaultClause(const OpenACCDefaultClause &Clause); + +#define VISIT_CLAUSE(CLAUSE_NAME) \ + void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &Clause); + +#include "clang/Basic/OpenACCClauses.def" }; /// Nothing to do here, there are no sub-statements. -void OpenACCClauseProfiler::VisitOpenACCDefaultClause( +void OpenACCClauseProfiler::VisitDefaultClause( const OpenACCDefaultClause &Clause) {} + +void OpenACCClauseProfiler::VisitIfClause(const OpenACCIfClause &Clause) { + assert(Clause.hasConditionExpr() && + "if clause requires a valid condition expr"); + Profiler.VisitStmt(Clause.getConditionExpr()); +} } // namespace void StmtProfiler::VisitOpenACCComputeConstruct( @@ -2469,7 +2480,7 @@ void StmtProfiler::VisitOpenACCComputeConstruct( // VisitStmt handles children, so the AssociatedStmt is handled. VisitStmt(S); - OpenACCClauseProfiler P; + OpenACCClauseProfiler P{*this}; P.VisitOpenACCClauseList(S->clauses()); } diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 085a7f51ce99ade39402cd4869b6487558bebe1c..688daa64d619744ed29e7fc6987edc9a2f89042d 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -397,6 +397,11 @@ void TextNodeDumper::Visit(const OpenACCClause *C) { case OpenACCClauseKind::Default: OS << '(' << cast(C)->getDefaultClauseKind() << ')'; break; + case OpenACCClauseKind::If: + // The condition expression will be printed as a part of the 'children', + // but print 'clause' here so it is clear what is happening from the dump. + OS << " clause"; + break; default: // Nothing to do here. break; @@ -1450,23 +1455,13 @@ void TextNodeDumper::VisitExpressionTraitExpr(const ExpressionTraitExpr *Node) { } void TextNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) { - if (Node->hasRewrittenInit()) { + if (Node->hasRewrittenInit()) OS << " has rewritten init"; - AddChild([=] { - ColorScope Color(OS, ShowColors, StmtColor); - Visit(Node->getExpr()); - }); - } } void TextNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) { - if (Node->hasRewrittenInit()) { + if (Node->hasRewrittenInit()) OS << " has rewritten init"; - AddChild([=] { - ColorScope Color(OS, ShowColors, StmtColor); - Visit(Node->getExpr()); - }); - } } void TextNodeDumper::VisitMaterializeTemporaryExpr( @@ -1966,6 +1961,9 @@ void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) { if (D->isTrivial()) OS << " trivial"; + if (const StringLiteral *M = D->getDeletedMessage()) + AddChild("delete message", [=] { Visit(M); }); + if (D->isIneligibleOrNotSelected()) OS << (isa(D) ? " not_selected" : " ineligible"); diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index 256365d66bb9074128d65c481a83165ff48a8b3a..bb212cde878826f157d6929d119145c0cde10a91 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -305,6 +305,10 @@ bool Module::directlyUses(const Module *Requested) { if (Requested->fullModuleNameIs({"_Builtin_stddef", "max_align_t"}) || Requested->fullModuleNameIs({"_Builtin_stddef_wint_t"})) return true; + // Darwin is allowed is to use our builtin 'ptrauth.h' and its accompanying + // module. + if (!Requested->Parent && Requested->Name == "ptrauth") + return true; if (NoUndeclaredIncludes) UndeclaredUses.insert(Requested); diff --git a/clang/lib/CIR/CMakeLists.txt b/clang/lib/CIR/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/lib/CMakeLists.txt b/clang/lib/CMakeLists.txt index 0cac86451f39e45c724a8655f4a9a6a6d499270b..14ba55360fe05096408292abb334a6943bdd7ac1 100644 --- a/clang/lib/CMakeLists.txt +++ b/clang/lib/CMakeLists.txt @@ -31,3 +31,7 @@ if(CLANG_INCLUDE_TESTS) endif() add_subdirectory(Interpreter) add_subdirectory(Support) + +if(CLANG_ENABLE_CIR) + add_subdirectory(CIR) +endif() diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index d35ce0409d723258cd82ec955071efa6d850921e..07452b18a85ea4905a1e8b412b2dbeef795b544d 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -1806,7 +1806,11 @@ void AtomicInfo::EmitAtomicUpdateOp( /*NumReservedValues=*/2); PHI->addIncoming(OldVal, CurBB); Address NewAtomicAddr = CreateTempAlloca(); - Address NewAtomicIntAddr = castToAtomicIntPointer(NewAtomicAddr); + Address NewAtomicIntAddr = + shouldCastToInt(NewAtomicAddr.getElementType(), /*CmpXchg=*/true) + ? castToAtomicIntPointer(NewAtomicAddr) + : NewAtomicAddr; + if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) || requiresMemSetZero(getAtomicAddress().getElementType())) { CGF.Builder.CreateStore(PHI, NewAtomicIntAddr); diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index c052367d287820bff7fb4498c84a5029775a32e0..9f95697f284c408943ec27c8d5e448b14865d4aa 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18194,7 +18194,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, Value *Op0 = EmitScalarExpr(E->getArg(0)); return Builder.CreateIntrinsic( /*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()), - Intrinsic::dx_any, ArrayRef{Op0}, nullptr, "dx.any"); + CGM.getHLSLRuntime().getAnyIntrinsic(), ArrayRef{Op0}, nullptr, + "hlsl.any"); } case Builtin::BI__builtin_hlsl_elementwise_clamp: { Value *OpX = EmitScalarExpr(E->getArg(0)); @@ -18303,9 +18304,16 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, Value *Op0 = EmitScalarExpr(E->getArg(0)); if (!E->getArg(0)->getType()->hasFloatingRepresentation()) llvm_unreachable("rcp operand must have a float representation"); - return Builder.CreateIntrinsic( - /*ReturnType=*/Op0->getType(), Intrinsic::dx_rcp, - ArrayRef{Op0}, nullptr, "dx.rcp"); + llvm::Type *Ty = Op0->getType(); + llvm::Type *EltTy = Ty->getScalarType(); + Constant *One = + Ty->isVectorTy() + ? ConstantVector::getSplat( + ElementCount::getFixed( + dyn_cast(Ty)->getNumElements()), + ConstantFP::get(EltTy, 1.0)) + : ConstantFP::get(EltTy, 1.0); + return Builder.CreateFDiv(One, Op0, "hlsl.rcp"); } case Builtin::BI__builtin_hlsl_elementwise_rsqrt: { Value *Op0 = EmitScalarExpr(E->getArg(0)); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 3f5463a9a70e9d81a9da46e76bebe8955f9b3073..7a0bc6fa77b889354209663c4eb6fba7057f4a04 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4124,7 +4124,8 @@ static bool isProvablyNull(llvm::Value *addr) { } static bool isProvablyNonNull(Address Addr, CodeGenFunction &CGF) { - return llvm::isKnownNonZero(Addr.getBasePointer(), CGF.CGM.getDataLayout()); + return llvm::isKnownNonZero(Addr.getBasePointer(), /*Depth=*/0, + CGF.CGM.getDataLayout()); } /// Emit the actual writing-back of a writeback. diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 8bdafa7c569b0802c860a4734b54dab7d74ff2bd..3f05ebb561da57d0c87c0387c7eb97512aaf3dd1 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -2216,8 +2216,11 @@ void CodeGenFunction::pushDestroyAndDeferDeactivation( void CodeGenFunction::pushDestroyAndDeferDeactivation( CleanupKind cleanupKind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray) { - pushCleanupAndDeferDeactivation( - cleanupKind, addr, type, destroyer, useEHCleanupForArray); + llvm::Instruction *DominatingIP = + Builder.CreateFlagLoad(llvm::Constant::getNullValue(Int8PtrTy)); + pushDestroy(cleanupKind, addr, type, destroyer, useEHCleanupForArray); + DeferredDeactivationCleanupStack.push_back( + {EHStack.stable_begin(), DominatingIP}); } void CodeGenFunction::pushStackRestore(CleanupKind Kind, Address SPMem) { diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 2b8073aef973f8e2a6391cdcf0701a609bcb1e41..506b364f5b2ec7110399dee74a54c195930cc9cc 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -73,6 +73,7 @@ public: //===----------------------------------------------------------------------===// GENERATE_HLSL_INTRINSIC_FUNCTION(All, all) + GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any) GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id) //===----------------------------------------------------------------------===// diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index 634a55fec5182eb76dc0439b25c045dbc63bfa37..868b1ab98e048ab4313042d12d9976a49998e734 100644 --- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -41,10 +41,11 @@ namespace { /// contains enough information to determine where the runs break. Microsoft /// and Itanium follow different rules and use different codepaths. /// * It is desired that, when possible, bitfields use the appropriate iN type -/// when lowered to llvm types. For example unsigned x : 24 gets lowered to +/// when lowered to llvm types. For example unsigned x : 24 gets lowered to /// i24. This isn't always possible because i24 has storage size of 32 bit -/// and if it is possible to use that extra byte of padding we must use -/// [i8 x 3] instead of i24. The function clipTailPadding does this. +/// and if it is possible to use that extra byte of padding we must use [i8 x +/// 3] instead of i24. This is computed when accumulating bitfields in +/// accumulateBitfields. /// C++ examples that require clipping: /// struct { int a : 24; char b; }; // a must be clipped, b goes at offset 3 /// struct A { int a : 24; ~A(); }; // a must be clipped because: @@ -62,11 +63,7 @@ namespace { /// that the tail padding is not used in the complete class.) However, /// because LLVM reads from the complete type it can generate incorrect code /// if we do not clip the tail padding off of the bitfield in the complete -/// layout. This introduces a somewhat awkward extra unnecessary clip stage. -/// The location of the clip is stored internally as a sentinel of type -/// SCISSOR. If LLVM were updated to read base types (which it probably -/// should because locations of things such as VBases are bogus in the llvm -/// type anyway) then we could eliminate the SCISSOR. +/// layout. /// * Itanium allows nearly empty primary virtual bases. These bases don't get /// get their own storage because they're laid out as part of another base /// or at the beginning of the structure. Determining if a VBase actually @@ -200,9 +197,7 @@ struct CGRecordLowering { const CXXRecordDecl *Query) const; void calculateZeroInit(); CharUnits calculateTailClippingOffset(bool isNonVirtualBaseType) const; - /// Lowers bitfield storage types to I8 arrays for bitfields with tail - /// padding that is or can potentially be used. - void clipTailPadding(); + void checkBitfieldClipping() const; /// Determines if we need a packed llvm struct. void determinePacked(bool NVBaseType); /// Inserts padding everywhere it's needed. @@ -305,7 +300,7 @@ void CGRecordLowering::lower(bool NVBaseType) { } llvm::stable_sort(Members); Members.push_back(StorageInfo(Size, getIntNType(8))); - clipTailPadding(); + checkBitfieldClipping(); determinePacked(NVBaseType); insertPadding(); Members.pop_back(); @@ -531,6 +526,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, // available padding characters. RecordDecl::field_iterator BestEnd = Begin; CharUnits BestEndOffset; + bool BestClipped; // Whether the representation must be in a byte array. for (;;) { // AtAlignedBoundary is true iff Field is the (potential) start of a new @@ -593,10 +589,9 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, // this is the best seen so far. BestEnd = Field; BestEndOffset = BeginOffset + AccessSize; - if (Types.getCodeGenOpts().FineGrainedBitfieldAccesses) - // Fine-grained access, so no merging of spans. - InstallBest = true; - else if (!BitSizeSinceBegin) + // Assume clipped until proven not below. + BestClipped = true; + if (!BitSizeSinceBegin) // A zero-sized initial span -- this will install nothing and reset // for another. InstallBest = true; @@ -624,6 +619,12 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, // The access unit is not at a naturally aligned offset within the // structure. InstallBest = true; + + if (InstallBest && BestEnd == Field) + // We're installing the first span, whose clipping was presumed + // above. Compute it correctly. + if (getSize(Type) == AccessSize) + BestClipped = false; } if (!InstallBest) { @@ -656,11 +657,15 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, // access unit. BestEndOffset = BeginOffset + TypeSize; BestEnd = Field; + BestClipped = false; } if (Barrier) // The next field is a barrier that we cannot merge across. InstallBest = true; + else if (Types.getCodeGenOpts().FineGrainedBitfieldAccesses) + // Fine-grained access, so no merging of spans. + InstallBest = true; else // Otherwise, we're not installing. Update the bit size // of the current span to go all the way to LimitOffset, which is @@ -679,7 +684,17 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, // Add the storage member for the access unit to the record. The // bitfields get the offset of their storage but come afterward and // remain there after a stable sort. - llvm::Type *Type = getIntNType(Context.toBits(AccessSize)); + llvm::Type *Type; + if (BestClipped) { + assert(getSize(getIntNType(Context.toBits(AccessSize))) > + AccessSize && + "Clipped access need not be clipped"); + Type = getByteArrayType(AccessSize); + } else { + Type = getIntNType(Context.toBits(AccessSize)); + assert(getSize(Type) == AccessSize && + "Unclipped access must be clipped"); + } Members.push_back(StorageInfo(BeginOffset, Type)); for (; Begin != BestEnd; ++Begin) if (!Begin->isZeroLengthBitField(Context)) @@ -934,32 +949,21 @@ void CGRecordLowering::calculateZeroInit() { } } -void CGRecordLowering::clipTailPadding() { - std::vector::iterator Prior = Members.begin(); - CharUnits Tail = getSize(Prior->Data); - for (std::vector::iterator Member = Prior + 1, - MemberEnd = Members.end(); - Member != MemberEnd; ++Member) { +// Verify accumulateBitfields computed the correct storage representations. +void CGRecordLowering::checkBitfieldClipping() const { +#ifndef NDEBUG + auto Tail = CharUnits::Zero(); + for (const auto &M : Members) { // Only members with data and the scissor can cut into tail padding. - if (!Member->Data && Member->Kind != MemberInfo::Scissor) + if (!M.Data && M.Kind != MemberInfo::Scissor) continue; - if (Member->Offset < Tail) { - assert(Prior->Kind == MemberInfo::Field && - "Only storage fields have tail padding!"); - if (!Prior->FD || Prior->FD->isBitField()) - Prior->Data = getByteArrayType(bitsToCharUnits(llvm::alignTo( - cast(Prior->Data)->getIntegerBitWidth(), 8))); - else { - assert(Prior->FD->hasAttr() && - "should not have reused this field's tail padding"); - Prior->Data = getByteArrayType( - Context.getTypeInfoDataSizeInChars(Prior->FD->getType()).Width); - } - } - if (Member->Data) - Prior = Member; - Tail = Prior->Offset + getSize(Prior->Data); + + assert(M.Offset >= Tail && "Bitfield access unit is not clipped"); + Tail = M.Offset; + if (M.Data) + Tail += getSize(M.Data); } +#endif } void CGRecordLowering::determinePacked(bool NVBaseType) { diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index bb9aaba025fa59899a12ad855041f48cf5a743ae..1a6b628016f7461a36427b5e2614bb25e98df482 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -25,8 +25,11 @@ #include "clang/CodeGen/ModuleBuilder.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendActions.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/MultiplexConsumer.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Serialization/ASTWriter.h" #include "llvm/ADT/Hashing.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" @@ -1003,6 +1006,12 @@ CodeGenerator *CodeGenAction::getCodeGenerator() const { return BEConsumer->getCodeGenerator(); } +bool CodeGenAction::BeginSourceFileAction(CompilerInstance &CI) { + if (CI.getFrontendOpts().GenReducedBMI) + CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleInterface); + return true; +} + static std::unique_ptr GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) { switch (Action) { @@ -1061,6 +1070,16 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { CI.getPreprocessor().addPPCallbacks(std::move(Callbacks)); } + if (CI.getFrontendOpts().GenReducedBMI && + !CI.getFrontendOpts().ModuleOutputPath.empty()) { + std::vector> Consumers(2); + Consumers[0] = std::make_unique( + CI.getPreprocessor(), CI.getModuleCache(), + CI.getFrontendOpts().ModuleOutputPath); + Consumers[1] = std::move(Result); + return std::make_unique(std::move(Consumers)); + } + return std::move(Result); } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 73a9cb9d6e0424ad38e0b874482015663766cbce..0c447b20cef40d6098b2c742a632ddeaf4ba64b3 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3952,8 +3952,20 @@ bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) { // behavior may break ABI compatibility of the current unit. if (const Module *M = F->getOwningModule(); M && M->getTopLevelModule()->isNamedModule() && - getContext().getCurrentNamedModule() != M->getTopLevelModule()) - return false; + getContext().getCurrentNamedModule() != M->getTopLevelModule()) { + // There are practices to mark template member function as always-inline + // and mark the template as extern explicit instantiation but not give + // the definition for member function. So we have to emit the function + // from explicitly instantiation with always-inline. + // + // See https://github.com/llvm/llvm-project/issues/86893 for details. + // + // TODO: Maybe it is better to give it a warning if we call a non-inline + // function from other module units which is marked as always-inline. + if (!F->isTemplateInstantiation() || !F->hasAttr()) { + return false; + } + } if (F->hasAttr()) return false; diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index e7335a61b10c533ecfafd5d3149a167a542518fb..0da92001e08c2701481b697ab3a30d7be6913bd7 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -4756,6 +4756,14 @@ Action *Driver::ConstructPhaseAction( if (Args.hasArg(options::OPT_extract_api)) return C.MakeAction(Input, types::TY_API_INFO); + // With 'fexperimental-modules-reduced-bmi', we don't want to run the + // precompile phase unless the user specified '--precompile'. In the case + // the '--precompile' flag is enabled, we will try to emit the reduced BMI + // as a by product in GenerateModuleInterfaceAction. + if (Args.hasArg(options::OPT_modules_reduced_bmi) && + !Args.getLastArg(options::OPT__precompile)) + return Input; + types::ID OutputTy = getPrecompiledType(Input->getType()); assert(OutputTy != types::TY_INVALID && "Cannot precompile this input type!"); @@ -5916,8 +5924,10 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, // If we're emitting a module output with the specified option // `-fmodule-output`. if (!AtTopLevel && isa(JA) && - JA.getType() == types::TY_ModuleFile && SpecifiedModuleOutput) + JA.getType() == types::TY_ModuleFile && SpecifiedModuleOutput) { + assert(!C.getArgs().hasArg(options::OPT_modules_reduced_bmi)); return GetModuleOutputPath(C, JA, BaseInput); + } // Output to a temporary file? if ((!AtTopLevel && !isSaveTempsEnabled() && diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 03450fc0f57b93e9acb16f1ece913f68d88f6a58..237092ed07e5dcf09dd90974d7a634d4cfecb507 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -796,7 +796,13 @@ ToolChain::getTargetSubDirPath(StringRef BaseDir) const { std::optional ToolChain::getRuntimePath() const { SmallString<128> P(D.ResourceDir); llvm::sys::path::append(P, "lib"); - return getTargetSubDirPath(P); + if (auto Ret = getTargetSubDirPath(P)) + return Ret; + // Darwin does not use per-target runtime directory. + if (Triple.isOSDarwin()) + return {}; + llvm::sys::path::append(P, Triple.str()); + return std::string(P); } std::optional ToolChain::getStdlibPath() const { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 766a9b91e3c0ada294a3dc4a33f3fa4aeeeca201..6d52eced10429693f2d02e1057d763e3f39db093 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4045,6 +4045,24 @@ static bool RenderModulesOptions(Compilation &C, const Driver &D, // module fragment. CmdArgs.push_back("-fskip-odr-check-in-gmf"); + if (Args.hasArg(options::OPT_modules_reduced_bmi) && + (Input.getType() == driver::types::TY_CXXModule || + Input.getType() == driver::types::TY_PP_CXXModule)) { + CmdArgs.push_back("-fexperimental-modules-reduced-bmi"); + + if (Args.hasArg(options::OPT_fmodule_output_EQ)) + Args.AddLastArg(CmdArgs, options::OPT_fmodule_output_EQ); + else + CmdArgs.push_back(Args.MakeArgString( + "-fmodule-output=" + + getCXX20NamedModuleOutputPath(Args, Input.getBaseInput()))); + } + + // Noop if we see '-fexperimental-modules-reduced-bmi' with other translation + // units than module units. This is more user friendly to allow end uers to + // enable this feature without asking for help from build systems. + Args.ClaimAllArgs(options::OPT_modules_reduced_bmi); + // We need to include the case the input file is a module file here. // Since the default compilation model for C++ module interface unit will // create temporary module file and compile the temporary module file diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 62a53b85ce098b89c83a54701e5c4e6d0bd63bd2..f10aa4dfaa9ddd9a9dde4679e8990240d63a1d44 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -114,6 +114,7 @@ static bool useFramePointerForTargetByDefault(const llvm::opt::ArgList &Args, case llvm::Triple::csky: case llvm::Triple::loongarch32: case llvm::Triple::loongarch64: + case llvm::Triple::m68k: return !clang::driver::tools::areOptimizationsEnabled(Args); default: break; diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index b00068c8098b9ab1ddb0df62949ac66fc28bedb1..b46bac24503ce1c64cfa0fa0c51a07164a986600 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -786,6 +786,10 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA, } } + // Pass the path to compiler resource files. + CmdArgs.push_back("-resource-dir"); + CmdArgs.push_back(D.ResourceDir.c_str()); + // Offloading related options addOffloadOptions(C, Inputs, JA, Args, CmdArgs); diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index 6c2f23e57bce05f0a112c3db6be3cbcfe896b1db..fb65881061effc3abc4f88028b48f889f8bab1ae 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -244,8 +244,9 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // Android ARM uses max-page-size=4096 to reduce VMA usage. ExtraOpts.push_back("-z"); ExtraOpts.push_back("max-page-size=4096"); - } else if (Triple.isAArch64()) { + } else if (Triple.isAArch64() || Triple.getArch() == llvm::Triple::x86_64) { // Android AArch64 uses max-page-size=16384 to support 4k/16k page sizes. + // Android emulates a 16k page size for app testing on x86_64 machines. ExtraOpts.push_back("-z"); ExtraOpts.push_back("max-page-size=16384"); } diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 700bce35c86839a516079441676cd21e5ff099c2..ad0e2c3c620c32b0fa4a88dd652670cae0f90a9a 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -684,7 +684,13 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, // arguments to function calls. We do this by ensuring that either all // arguments (including any lambdas) go on the same line as the function // call, or we break before the first argument. - auto PrevNonComment = Current.getPreviousNonComment(); + const auto *Prev = Current.Previous; + if (!Prev) + return false; + // For example, `/*Newline=*/false`. + if (Prev->is(TT_BlockComment) && Current.SpacesRequiredBefore == 0) + return false; + const auto *PrevNonComment = Current.getPreviousNonComment(); if (!PrevNonComment || PrevNonComment->isNot(tok::l_paren)) return false; if (Current.isOneOf(tok::comment, tok::l_paren, TT_LambdaLSquare)) diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 89e6c19b0af45c10e975c36f50fbbc3ca2ad85ba..ccb2c9190e2eff0bdb551c3ecb95dde3c987639d 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -3891,7 +3891,11 @@ static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { FileName.ends_with_insensitive(".protodevel")) { return FormatStyle::LK_Proto; } - if (FileName.ends_with_insensitive(".textpb") || + // txtpb is the canonical extension, and textproto is the legacy canonical + // extension + // https://protobuf.dev/reference/protobuf/textformat-spec/#text-format-files + if (FileName.ends_with_insensitive(".txtpb") || + FileName.ends_with_insensitive(".textpb") || FileName.ends_with_insensitive(".pb.txt") || FileName.ends_with_insensitive(".textproto") || FileName.ends_with_insensitive(".asciipb")) { diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 642b14d8b09d944e4832fa3bf7545d745ccadf53..04eb104132671357f84a8d74b070636bff90087e 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -281,6 +281,13 @@ GenerateModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI, if (Consumers.empty()) return nullptr; + if (CI.getFrontendOpts().GenReducedBMI && + !CI.getFrontendOpts().ModuleOutputPath.empty()) { + Consumers.push_back(std::make_unique( + CI.getPreprocessor(), CI.getModuleCache(), + CI.getFrontendOpts().ModuleOutputPath)); + } + return std::make_unique(std::move(Consumers)); } diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 84069e96f41464b5e649ad0ffa93220e9102aef8..4f44c3b7b89d4d860ad3815fb77c23557fcb1b37 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -747,6 +747,9 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, Builder.defineMacro("__cpp_named_character_escapes", "202207L"); Builder.defineMacro("__cpp_placeholder_variables", "202306L"); + // C++26 features supported in earlier language modes. + Builder.defineMacro("__cpp_deleted_function", "202403L"); + if (LangOpts.Char8) Builder.defineMacro("__cpp_char8_t", "202207L"); Builder.defineMacro("__cpp_impl_destroying_delete", "201806L"); diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index 97104ccd8db59c5a7db747e1bb1375cc92d177d3..e6ae4e19e81db9c13b2aeb040714c747c9953e56 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -437,14 +437,14 @@ foreach( f ${generated_files} ) endforeach( f ) function(add_header_target target_name file_list) - add_custom_target(${target_name} DEPENDS ${file_list}) + add_library(${target_name} INTERFACE ${file_list}) set_target_properties(${target_name} PROPERTIES FOLDER "Misc" RUNTIME_OUTPUT_DIRECTORY "${output_dir}") endfunction() # The catch-all clang-resource-headers target -add_custom_target("clang-resource-headers" ALL DEPENDS ${out_files}) +add_library(clang-resource-headers INTERFACE ${out_files}) set_target_properties("clang-resource-headers" PROPERTIES FOLDER "Misc" RUNTIME_OUTPUT_DIRECTORY "${output_dir}") @@ -501,6 +501,10 @@ add_header_target("windows-resource-headers" ${windows_only_files}) add_header_target("utility-resource-headers" ${utility_files}) get_clang_resource_dir(header_install_dir SUBDIR include) +target_include_directories(clang-resource-headers INTERFACE + $ + $) +set_property(GLOBAL APPEND PROPERTY CLANG_EXPORTS clang-resource-headers) ############################################################# # Install rules for the catch-all clang-resource-headers target diff --git a/clang/lib/InstallAPI/DylibVerifier.cpp b/clang/lib/InstallAPI/DylibVerifier.cpp index 4fa2d4e9292c72e2307f9eb5712f1f8b2dd324e0..84d9b5892e88da14471d78a4ada28cd4f2a86012 100644 --- a/clang/lib/InstallAPI/DylibVerifier.cpp +++ b/clang/lib/InstallAPI/DylibVerifier.cpp @@ -176,7 +176,13 @@ void DylibVerifier::addSymbol(const Record *R, SymbolContext &SymCtx, bool DylibVerifier::shouldIgnoreObsolete(const Record *R, SymbolContext &SymCtx, const Record *DR) { - return SymCtx.FA->Avail.isObsoleted(); + if (!SymCtx.FA->Avail.isObsoleted()) + return false; + + if (Zippered) + DeferredZipperedSymbols[SymCtx.SymbolName].emplace_back(ZipperedDeclSource{ + SymCtx.FA, &Ctx.Diag->getSourceManager(), Ctx.Target}); + return true; } bool DylibVerifier::shouldIgnoreReexport(const Record *R, @@ -195,6 +201,28 @@ bool DylibVerifier::shouldIgnoreReexport(const Record *R, return false; } +bool DylibVerifier::shouldIgnoreInternalZipperedSymbol( + const Record *R, const SymbolContext &SymCtx) const { + if (!Zippered) + return false; + + return Exports->findSymbol(SymCtx.Kind, SymCtx.SymbolName, + SymCtx.ObjCIFKind) != nullptr; +} + +bool DylibVerifier::shouldIgnoreZipperedAvailability(const Record *R, + SymbolContext &SymCtx) { + if (!(Zippered && SymCtx.FA->Avail.isUnavailable())) + return false; + + // Collect source location incase there is an exported symbol to diagnose + // during `verifyRemainingSymbols`. + DeferredZipperedSymbols[SymCtx.SymbolName].emplace_back( + ZipperedDeclSource{SymCtx.FA, SourceManagers.back().get(), Ctx.Target}); + + return true; +} + bool DylibVerifier::compareObjCInterfaceSymbols(const Record *R, SymbolContext &SymCtx, const ObjCInterfaceRecord *DR) { @@ -294,6 +322,9 @@ DylibVerifier::Result DylibVerifier::compareVisibility(const Record *R, if (shouldIgnorePrivateExternAttr(SymCtx.FA->D)) return Result::Ignore; + if (shouldIgnoreInternalZipperedSymbol(R, SymCtx)) + return Result::Ignore; + unsigned ID; Result Outcome; if (Mode == VerificationMode::ErrorsAndWarnings) { @@ -321,6 +352,9 @@ DylibVerifier::Result DylibVerifier::compareAvailability(const Record *R, if (!SymCtx.FA->Avail.isUnavailable()) return Result::Valid; + if (shouldIgnoreZipperedAvailability(R, SymCtx)) + return Result::Ignore; + const bool IsDeclAvailable = SymCtx.FA->Avail.isUnavailable(); switch (Mode) { @@ -588,13 +622,58 @@ void DylibVerifier::visitSymbolInDylib(const Record &R, SymbolContext &SymCtx) { } } + const bool IsLinkerSymbol = SymbolName.starts_with("$ld$"); + + if (R.isVerified()) { + // Check for unavailable symbols. + // This should only occur in the zippered case where we ignored + // availability until all headers have been parsed. + auto It = DeferredZipperedSymbols.find(SymCtx.SymbolName); + if (It == DeferredZipperedSymbols.end()) { + updateState(Result::Valid); + return; + } + + ZipperedDeclSources Locs; + for (const ZipperedDeclSource &ZSource : It->second) { + if (ZSource.FA->Avail.isObsoleted()) { + updateState(Result::Ignore); + return; + } + if (ZSource.T.Arch != Ctx.Target.Arch) + continue; + Locs.emplace_back(ZSource); + } + assert(Locs.size() == 2 && "Expected two decls for zippered symbol"); + + // Print violating declarations per platform. + for (const ZipperedDeclSource &ZSource : Locs) { + unsigned DiagID = 0; + if (Mode == VerificationMode::Pedantic || IsLinkerSymbol) { + updateState(Result::Invalid); + DiagID = diag::err_header_availability_mismatch; + } else if (Mode == VerificationMode::ErrorsAndWarnings) { + updateState(Result::Ignore); + DiagID = diag::warn_header_availability_mismatch; + } else { + updateState(Result::Ignore); + return; + } + // Bypass emitDiag banner and print the target everytime. + Ctx.Diag->setSourceManager(ZSource.SrcMgr); + Ctx.Diag->Report(diag::warn_target) << getTargetTripleName(ZSource.T); + Ctx.Diag->Report(ZSource.FA->Loc, DiagID) + << getAnnotatedName(&R, SymCtx) << ZSource.FA->Avail.isUnavailable() + << ZSource.FA->Avail.isUnavailable(); + } + return; + } + if (shouldIgnoreCpp(SymbolName, R.isWeakDefined())) { updateState(Result::Valid); return; } - const bool IsLinkerSymbol = SymbolName.starts_with("$ld$"); - // All checks at this point classify as some kind of violation. // The different verification modes dictate whether they are reported to the // user. @@ -647,8 +726,6 @@ void DylibVerifier::visitSymbolInDylib(const Record &R, SymbolContext &SymCtx) { } void DylibVerifier::visitGlobal(const GlobalRecord &R) { - if (R.isVerified()) - return; SymbolContext SymCtx; SimpleSymbol Sym = parseSymbol(R.getName()); SymCtx.SymbolName = Sym.Name; @@ -658,8 +735,6 @@ void DylibVerifier::visitGlobal(const GlobalRecord &R) { void DylibVerifier::visitObjCIVar(const ObjCIVarRecord &R, const StringRef Super) { - if (R.isVerified()) - return; SymbolContext SymCtx; SymCtx.SymbolName = ObjCIVarRecord::createScopedName(Super, R.getName()); SymCtx.Kind = EncodeKind::ObjectiveCInstanceVariable; @@ -679,8 +754,6 @@ void DylibVerifier::accumulateSrcLocForDylibSymbols() { } void DylibVerifier::visitObjCInterface(const ObjCInterfaceRecord &R) { - if (R.isVerified()) - return; SymbolContext SymCtx; SymCtx.SymbolName = R.getName(); SymCtx.ObjCIFKind = assignObjCIFSymbolKind(&R); @@ -713,9 +786,12 @@ DylibVerifier::Result DylibVerifier::verifyRemainingSymbols() { DWARFContext DWARFInfo; DWARFCtx = &DWARFInfo; - Ctx.DiscoveredFirstError = false; - Ctx.PrintArch = true; + Ctx.Target = Target(Architecture::AK_unknown, PlatformType::PLATFORM_UNKNOWN); for (std::shared_ptr Slice : Dylib) { + if (Ctx.Target.Arch == Slice->getTarget().Arch) + continue; + Ctx.DiscoveredFirstError = false; + Ctx.PrintArch = true; Ctx.Target = Slice->getTarget(); Ctx.DylibSlice = Slice.get(); Slice->visit(*this); diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index f0750e5336b6a507c7ab42b6c797daedfa8f03bc..0632882b2961469c2c905b4c8a951e6bb6683937 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -946,9 +946,13 @@ OptionalFileEntryRef HeaderSearch::LookupFile( // If we have no includer, that means we're processing a #include // from a module build. We should treat this as a system header if we're // building a [system] module. - bool IncluderIsSystemHeader = - Includer ? getFileInfo(*Includer).DirInfo != SrcMgr::C_User : - BuildSystemModule; + bool IncluderIsSystemHeader = [&]() { + if (!Includer) + return BuildSystemModule; + const HeaderFileInfo *HFI = getExistingFileInfo(*Includer); + assert(HFI && "includer without file info"); + return HFI->DirInfo != SrcMgr::C_User; + }(); if (OptionalFileEntryRef FE = getFileAndSuggestModule( TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader, RequestingModule, SuggestedModule)) { @@ -963,10 +967,11 @@ OptionalFileEntryRef HeaderSearch::LookupFile( // Note that we only use one of FromHFI/ToHFI at once, due to potential // reallocation of the underlying vector potentially making the first // reference binding dangling. - HeaderFileInfo &FromHFI = getFileInfo(*Includer); - unsigned DirInfo = FromHFI.DirInfo; - bool IndexHeaderMapHeader = FromHFI.IndexHeaderMapHeader; - StringRef Framework = FromHFI.Framework; + const HeaderFileInfo *FromHFI = getExistingFileInfo(*Includer); + assert(FromHFI && "includer without file info"); + unsigned DirInfo = FromHFI->DirInfo; + bool IndexHeaderMapHeader = FromHFI->IndexHeaderMapHeader; + StringRef Framework = FromHFI->Framework; HeaderFileInfo &ToHFI = getFileInfo(*FE); ToHFI.DirInfo = DirInfo; @@ -1153,10 +1158,12 @@ OptionalFileEntryRef HeaderSearch::LookupFile( // "Foo" is the name of the framework in which the including header was found. if (!Includers.empty() && Includers.front().first && !isAngled && !Filename.contains('/')) { - HeaderFileInfo &IncludingHFI = getFileInfo(*Includers.front().first); - if (IncludingHFI.IndexHeaderMapHeader) { + const HeaderFileInfo *IncludingHFI = + getExistingFileInfo(*Includers.front().first); + assert(IncludingHFI && "includer without file info"); + if (IncludingHFI->IndexHeaderMapHeader) { SmallString<128> ScratchFilename; - ScratchFilename += IncludingHFI.Framework; + ScratchFilename += IncludingHFI->Framework; ScratchFilename += '/'; ScratchFilename += Filename; @@ -1286,11 +1293,11 @@ OptionalFileEntryRef HeaderSearch::LookupSubframeworkHeader( } // This file is a system header or C++ unfriendly if the old file is. - // - // Note that the temporary 'DirInfo' is required here, as either call to - // getFileInfo could resize the vector and we don't want to rely on order - // of evaluation. - unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo; + const HeaderFileInfo *ContextHFI = getExistingFileInfo(ContextFileEnt); + assert(ContextHFI && "context file without file info"); + // Note that the temporary 'DirInfo' is required here, as the call to + // getFileInfo could resize the vector and might invalidate 'ContextHFI'. + unsigned DirInfo = ContextHFI->DirInfo; getFileInfo(*File).DirInfo = DirInfo; FrameworkName.pop_back(); // remove the trailing '/' @@ -1348,8 +1355,6 @@ static void mergeHeaderFileInfo(HeaderFileInfo &HFI, HFI.Framework = OtherHFI.Framework; } -/// getFileInfo - Return the HeaderFileInfo structure for the specified -/// FileEntry. HeaderFileInfo &HeaderSearch::getFileInfo(FileEntryRef FE) { if (FE.getUID() >= FileInfo.size()) FileInfo.resize(FE.getUID() + 1); @@ -1366,27 +1371,20 @@ HeaderFileInfo &HeaderSearch::getFileInfo(FileEntryRef FE) { } HFI->IsValid = true; - // We have local information about this header file, so it's no longer - // strictly external. + // We assume the caller has local information about this header file, so it's + // no longer strictly external. HFI->External = false; return *HFI; } -const HeaderFileInfo * -HeaderSearch::getExistingFileInfo(FileEntryRef FE, bool WantExternal) const { - // If we have an external source, ensure we have the latest information. - // FIXME: Use a generation count to check whether this is really up to date. +const HeaderFileInfo *HeaderSearch::getExistingFileInfo(FileEntryRef FE) const { HeaderFileInfo *HFI; if (ExternalSource) { - if (FE.getUID() >= FileInfo.size()) { - if (!WantExternal) - return nullptr; + if (FE.getUID() >= FileInfo.size()) FileInfo.resize(FE.getUID() + 1); - } HFI = &FileInfo[FE.getUID()]; - if (!WantExternal && (!HFI->IsValid || HFI->External)) - return nullptr; + // FIXME: Use a generation count to check whether this is really up to date. if (!HFI->Resolved) { auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE); if (ExternalHFI.IsValid) { @@ -1395,16 +1393,25 @@ HeaderSearch::getExistingFileInfo(FileEntryRef FE, bool WantExternal) const { mergeHeaderFileInfo(*HFI, ExternalHFI); } } - } else if (FE.getUID() >= FileInfo.size()) { - return nullptr; - } else { + } else if (FE.getUID() < FileInfo.size()) { HFI = &FileInfo[FE.getUID()]; + } else { + HFI = nullptr; } - if (!HFI->IsValid || (HFI->External && !WantExternal)) - return nullptr; + return (HFI && HFI->IsValid) ? HFI : nullptr; +} + +const HeaderFileInfo * +HeaderSearch::getExistingLocalFileInfo(FileEntryRef FE) const { + HeaderFileInfo *HFI; + if (FE.getUID() < FileInfo.size()) { + HFI = &FileInfo[FE.getUID()]; + } else { + HFI = nullptr; + } - return HFI; + return (HFI && HFI->IsValid && !HFI->External) ? HFI : nullptr; } bool HeaderSearch::isFileMultipleIncludeGuarded(FileEntryRef File) const { diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index d790060c17c0496130add0aeeb379597fce6b6f6..d054eda279b8c874b50c6844fc7dd2b593e77b80 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -20,6 +20,49 @@ using namespace clang; +/// Parse the optional ("message") part of a deleted-function-body. +StringLiteral *Parser::ParseCXXDeletedFunctionMessage() { + if (!Tok.is(tok::l_paren)) + return nullptr; + StringLiteral *Message = nullptr; + BalancedDelimiterTracker BT{*this, tok::l_paren}; + BT.consumeOpen(); + + if (isTokenStringLiteral()) { + ExprResult Res = ParseUnevaluatedStringLiteralExpression(); + if (Res.isUsable()) { + Message = Res.getAs(); + Diag(Message->getBeginLoc(), getLangOpts().CPlusPlus26 + ? diag::warn_cxx23_delete_with_message + : diag::ext_delete_with_message) + << Message->getSourceRange(); + } + } else { + Diag(Tok.getLocation(), diag::err_expected_string_literal) + << /*Source='in'*/ 0 << "'delete'"; + SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch); + } + + BT.consumeClose(); + return Message; +} + +/// If we've encountered '= delete' in a context where it is ill-formed, such +/// as in the declaration of a non-function, also skip the ("message") part if +/// it is present to avoid issuing further diagnostics. +void Parser::SkipDeletedFunctionBody() { + if (!Tok.is(tok::l_paren)) + return; + + BalancedDelimiterTracker BT{*this, tok::l_paren}; + BT.consumeOpen(); + + // Just skip to the end of the current declaration. + SkipUntil(tok::r_paren, tok::comma, StopAtSemi | StopBeforeMatch); + if (Tok.is(tok::r_paren)) + BT.consumeClose(); +} + /// ParseCXXInlineMethodDef - We parsed and verified that the specified /// Declarator is a well formed C++ inline method definition. Now lex its body /// and store its tokens for parsing after the C++ class is complete. @@ -70,7 +113,8 @@ NamedDecl *Parser::ParseCXXInlineMethodDef( ? diag::warn_cxx98_compat_defaulted_deleted_function : diag::ext_defaulted_deleted_function) << 1 /* deleted */; - Actions.SetDeclDeleted(FnD, KWLoc); + StringLiteral *Message = ParseCXXDeletedFunctionMessage(); + Actions.SetDeclDeleted(FnD, KWLoc, Message); Delete = true; if (auto *DeclAsFunction = dyn_cast(FnD)) { DeclAsFunction->setRangeEnd(KWEndLoc); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 583232f2d610d0aebb4bb47873c4a3b81327f863..2b934234b7cf5ddccfe84c6353e4fb052a9d5715 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -26,6 +26,7 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" @@ -2379,10 +2380,6 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, if (getLangOpts().CPlusPlus23) { auto &LastRecord = Actions.ExprEvalContexts.back(); LastRecord.InLifetimeExtendingContext = true; - - // Materialize non-`cv void` prvalue temporaries in discarded - // expressions. These materialized temporaries may be lifetime-extented. - LastRecord.InMaterializeTemporaryObjectContext = true; } if (getLangOpts().OpenMP) @@ -2664,7 +2661,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( } } - Sema::CUDATargetContextRAII X(Actions, Sema::CTCK_InitGlobalVar, ThisDecl); + SemaCUDA::CUDATargetContextRAII X(Actions.CUDA(), + SemaCUDA::CTCK_InitGlobalVar, ThisDecl); switch (TheInitKind) { // Parse declarator '=' initializer. case InitKind::Equal: { @@ -2676,6 +2674,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( << 1 /* delete */; else Diag(ConsumeToken(), diag::err_deleted_non_function); + SkipDeletedFunctionBody(); } else if (Tok.is(tok::kw_default)) { if (D.isFunctionDeclarator()) Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration) diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 477d81cdc2c230b53521003b826cf558985a82e5..cd4803d51bc1de0759885fbf1017ebd64837c09c 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -3397,6 +3397,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, << 1 /* delete */; else Diag(ConsumeToken(), diag::err_deleted_non_function); + SkipDeletedFunctionBody(); return ExprError(); } } else if (Tok.is(tok::kw_default)) { diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index d08e675604d19c511e369aaff88a70d21b790e7d..473ec9afd60181208f4441b557971eddf9c2595e 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -30,6 +30,7 @@ #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaSYCL.h" #include "clang/Sema/TypoCorrection.h" #include "llvm/ADT/SmallVector.h" @@ -2129,10 +2130,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { } if (!LHS.isInvalid()) { - ExprResult ECResult = Actions.ActOnCUDAExecConfigExpr(getCurScope(), - OpenLoc, - ExecConfigExprs, - CloseLoc); + ExprResult ECResult = Actions.CUDA().ActOnExecConfigExpr( + getCurScope(), OpenLoc, ExecConfigExprs, CloseLoc); if (ECResult.isInvalid()) LHS = ExprError(); else diff --git a/clang/lib/Parse/ParseHLSL.cpp b/clang/lib/Parse/ParseHLSL.cpp index 5afc958600fa558148d39b128900bbb8454fd473..d97985d42369ad9626a31ff83f725af40a4bf4b9 100644 --- a/clang/lib/Parse/ParseHLSL.cpp +++ b/clang/lib/Parse/ParseHLSL.cpp @@ -72,9 +72,9 @@ Decl *Parser::ParseHLSLBuffer(SourceLocation &DeclEnd) { return nullptr; } - Decl *D = Actions.HLSL().ActOnStartHLSLBuffer( - getCurScope(), IsCBuffer, BufferLoc, Identifier, IdentifierLoc, - T.getOpenLocation()); + Decl *D = Actions.HLSL().ActOnStartBuffer(getCurScope(), IsCBuffer, BufferLoc, + Identifier, IdentifierLoc, + T.getOpenLocation()); while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { // FIXME: support attribute on constants inside cbuffer/tbuffer. @@ -88,7 +88,7 @@ Decl *Parser::ParseHLSLBuffer(SourceLocation &DeclEnd) { T.skipToEnd(); DeclEnd = T.getCloseLocation(); BufferScope.Exit(); - Actions.HLSL().ActOnFinishHLSLBuffer(D, DeclEnd); + Actions.HLSL().ActOnFinishBuffer(D, DeclEnd); return nullptr; } } @@ -96,7 +96,7 @@ Decl *Parser::ParseHLSLBuffer(SourceLocation &DeclEnd) { T.consumeClose(); DeclEnd = T.getCloseLocation(); BufferScope.Exit(); - Actions.HLSL().ActOnFinishHLSLBuffer(D, DeclEnd); + Actions.HLSL().ActOnFinishBuffer(D, DeclEnd); Actions.ProcessDeclAttributeList(Actions.CurScope, D, Attrs); return D; diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index b487a1968d1ec87192aefb904b4524b48fc90d06..91f2b8afcf0c241759cb315f629eecf12e6c8940 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -535,14 +535,6 @@ bool ClauseHasRequiredParens(OpenACCDirectiveKind DirKind, return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Required; } -ExprResult ParseOpenACCConditionalExpr(Parser &P) { - // FIXME: It isn't clear if the spec saying 'condition' means the same as - // it does in an if/while/etc (See ParseCXXCondition), however as it was - // written with Fortran/C in mind, we're going to assume it just means an - // 'expression evaluating to boolean'. - return P.getActions().CorrectDelayedTyposInExpr(P.ParseExpression()); -} - // Skip until we see the end of pragma token, but don't consume it. This is us // just giving up on the rest of the pragma so we can continue executing. We // have to do this because 'SkipUntil' considers paren balancing, which isn't @@ -595,6 +587,23 @@ Parser::OpenACCClauseParseResult Parser::OpenACCSuccess(OpenACCClause *Clause) { return {Clause, OpenACCParseCanContinue::Can}; } +ExprResult Parser::ParseOpenACCConditionExpr() { + // FIXME: It isn't clear if the spec saying 'condition' means the same as + // it does in an if/while/etc (See ParseCXXCondition), however as it was + // written with Fortran/C in mind, we're going to assume it just means an + // 'expression evaluating to boolean'. + ExprResult ER = getActions().CorrectDelayedTyposInExpr(ParseExpression()); + + if (!ER.isUsable()) + return ER; + + Sema::ConditionResult R = + getActions().ActOnCondition(getCurScope(), ER.get()->getExprLoc(), + ER.get(), Sema::ConditionKind::Boolean); + + return R.isInvalid() ? ExprError() : R.get().second; +} + // OpenACC 3.3, section 1.7: // To simplify the specification and convey appropriate constraint information, // a pqr-list is a comma-separated list of pdr items. The one exception is a @@ -842,12 +851,15 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( break; } case OpenACCClauseKind::If: { - ExprResult CondExpr = ParseOpenACCConditionalExpr(*this); + ExprResult CondExpr = ParseOpenACCConditionExpr(); + ParsedClause.setConditionDetails(CondExpr.isUsable() ? CondExpr.get() + : nullptr); if (CondExpr.isInvalid()) { Parens.skipToEnd(); return OpenACCCanContinue(); } + break; } case OpenACCClauseKind::CopyIn: @@ -964,7 +976,7 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( switch (ClauseKind) { case OpenACCClauseKind::Self: { assert(DirKind != OpenACCDirectiveKind::Update); - ExprResult CondExpr = ParseOpenACCConditionalExpr(*this); + ExprResult CondExpr = ParseOpenACCConditionExpr(); if (CondExpr.isInvalid()) { Parens.skipToEnd(); diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 0f692e2146a4901df7411ab11bfefa2746959fce..3979f75b6020dbba3d91ae2e747aac6bbcdf996a 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -21,6 +21,7 @@ #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaCUDA.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringSwitch.h" #include @@ -3900,8 +3901,8 @@ void PragmaForceCUDAHostDeviceHandler::HandlePragma( } if (Info->isStr("begin")) - Actions.PushForceCUDAHostDevice(); - else if (!Actions.PopForceCUDAHostDevice()) + Actions.CUDA().PushForceHostDevice(); + else if (!Actions.CUDA().PopForceHostDevice()) PP.Diag(FirstTok.getLocation(), diag::err_pragma_cannot_end_force_cuda_host_device); diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index cc0e41ed221c4f1d0058ea30a685e5ad01045824..d6f2b9f448cd5259220a5060d76ec5a51e1bcb19 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1404,6 +1404,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // Parse function body eagerly if it is either '= delete;' or '= default;' as // ActOnStartOfFunctionDef needs to know whether the function is deleted. + StringLiteral *DeletedMessage = nullptr; Sema::FnBodyKind BodyKind = Sema::FnBodyKind::Other; SourceLocation KWLoc; if (TryConsumeToken(tok::equal)) { @@ -1415,6 +1416,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, : diag::ext_defaulted_deleted_function) << 1 /* deleted */; BodyKind = Sema::FnBodyKind::Delete; + DeletedMessage = ParseCXXDeletedFunctionMessage(); } else if (TryConsumeToken(tok::kw_default, KWLoc)) { Diag(KWLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_defaulted_deleted_function @@ -1473,7 +1475,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, D.getMutableDeclSpec().abort(); if (BodyKind != Sema::FnBodyKind::Other) { - Actions.SetFunctionBodyKind(Res, KWLoc, BodyKind); + Actions.SetFunctionBodyKind(Res, KWLoc, BodyKind, DeletedMessage); Stmt *GeneratedBody = Res ? Res->getBody() : nullptr; Actions.ActOnFinishFunctionBody(Res, GeneratedBody, false); return Res; diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index ab3b813a9ccd97efc5d99104cd1d493024aff78a..a96439df664228673d2bbe2d1aedbf7dce64e2f3 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_LINK_COMPONENTS Core + Demangle FrontendHLSL FrontendOpenMP MC diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index a2ea66f339c8e37e8f914f0845af191bcd71db6d..8de202f4f7a0c32c4dc12f3413faed50b94272e5 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -41,6 +41,7 @@ #include "clang/Sema/RISCVIntrinsicManager.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaConsumer.h" #include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" @@ -199,6 +200,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), CurContext(nullptr), ExternalSource(nullptr), CurScope(nullptr), Ident_super(nullptr), + CUDAPtr(std::make_unique(*this)), HLSLPtr(std::make_unique(*this)), OpenACCPtr(std::make_unique(*this)), SYCLPtr(std::make_unique(*this)), @@ -1635,15 +1637,15 @@ bool Sema::hasUncompilableErrorOccurred() const { // Print notes showing how we can reach FD starting from an a priori // known-callable function. static void emitCallStackNotes(Sema &S, const FunctionDecl *FD) { - auto FnIt = S.DeviceKnownEmittedFns.find(FD); - while (FnIt != S.DeviceKnownEmittedFns.end()) { + auto FnIt = S.CUDA().DeviceKnownEmittedFns.find(FD); + while (FnIt != S.CUDA().DeviceKnownEmittedFns.end()) { // Respect error limit. if (S.Diags.hasFatalErrorOccurred()) return; DiagnosticBuilder Builder( S.Diags.Report(FnIt->second.Loc, diag::note_called_by)); Builder << FnIt->second.FD; - FnIt = S.DeviceKnownEmittedFns.find(FnIt->second.FD); + FnIt = S.CUDA().DeviceKnownEmittedFns.find(FnIt->second.FD); } } @@ -1747,7 +1749,7 @@ public: (ShouldEmitRootNode || InOMPDeviceContext)) S.finalizeOpenMPDelayedAnalysis(Caller, FD, Loc); if (Caller) - S.DeviceKnownEmittedFns[FD] = {Caller, Loc}; + S.CUDA().DeviceKnownEmittedFns[FD] = {Caller, Loc}; // Always emit deferred diagnostics for the direct users. This does not // lead to explosion of diagnostics since each user is visited at most // twice. @@ -1836,8 +1838,8 @@ void Sema::emitDeferredDiags() { // which other not-known-emitted functions. // // When we see something which is illegal if the current function is emitted -// (usually by way of CUDADiagIfDeviceCode, CUDADiagIfHostCode, or -// CheckCUDACall), we first check if the current function is known-emitted. If +// (usually by way of DiagIfDeviceCode, DiagIfHostCode, or +// CheckCall), we first check if the current function is known-emitted. If // so, we immediately output the diagnostic. // // Otherwise, we "defer" the diagnostic. It sits in Sema::DeviceDeferredDiags @@ -1900,8 +1902,8 @@ Sema::targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD) { ? diagIfOpenMPDeviceCode(Loc, DiagID, FD) : diagIfOpenMPHostCode(Loc, DiagID, FD); if (getLangOpts().CUDA) - return getLangOpts().CUDAIsDevice ? CUDADiagIfDeviceCode(Loc, DiagID) - : CUDADiagIfHostCode(Loc, DiagID); + return getLangOpts().CUDAIsDevice ? CUDA().DiagIfDeviceCode(Loc, DiagID) + : CUDA().DiagIfHostCode(Loc, DiagID); if (getLangOpts().SYCLIsDevice) return SYCL().DiagIfDeviceCode(Loc, DiagID); diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index a3128306c664fe17ffa439ceda3dda798c2e2f50..4c445f28bba8c62debc5ba52dfc1b0897c4f7459 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -463,6 +463,8 @@ static void ProcessAPINotes(Sema &S, FunctionOrMethod AnyFunc, D = MD; } + assert((FD || MD) && "Expecting Function or ObjCMethod"); + // Nullability of return type. if (Info.NullabilityAudited) applyNullability(S, D, Info.getReturnTypeInfo(), Metadata); diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 4af3c0f30a8e8a23e4a59bd733645cc2556f21bb..6a707eeb66d012ba49b8b4f466b2d83a920a3409 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -10,8 +10,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/Basic/Specifiers.h" -#include "clang/Sema/SemaInternal.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" @@ -19,9 +17,12 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DependentDiagnostic.h" #include "clang/AST/ExprCXX.h" +#include "clang/Basic/Specifiers.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/SemaInternal.h" +#include "llvm/ADT/STLForwardCompat.h" using namespace clang; using namespace sema; @@ -1658,21 +1659,24 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, case InitializedEntity::EK_Base: PD = PDiag(diag::err_access_base_ctor); PD << Entity.isInheritedVirtualBase() - << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor); + << Entity.getBaseSpecifier()->getType() + << llvm::to_underlying(getSpecialMember(Constructor)); break; case InitializedEntity::EK_Member: case InitializedEntity::EK_ParenAggInitMember: { const FieldDecl *Field = cast(Entity.getDecl()); PD = PDiag(diag::err_access_field_ctor); - PD << Field->getType() << getSpecialMember(Constructor); + PD << Field->getType() + << llvm::to_underlying(getSpecialMember(Constructor)); break; } case InitializedEntity::EK_LambdaCapture: { StringRef VarName = Entity.getCapturedVarName(); PD = PDiag(diag::err_access_lambda_capture); - PD << VarName << Entity.getType() << getSpecialMember(Constructor); + PD << VarName << Entity.getType() + << llvm::to_underlying(getSpecialMember(Constructor)); break; } diff --git a/clang/lib/Sema/SemaBase.cpp b/clang/lib/Sema/SemaBase.cpp index 95c0cfbe283b0e3a81bc0e69b9ebf3ba893fe053..0442fb2929e3c647f94a4f3a927fe8af960d05d4 100644 --- a/clang/lib/Sema/SemaBase.cpp +++ b/clang/lib/Sema/SemaBase.cpp @@ -1,5 +1,6 @@ #include "clang/Sema/SemaBase.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaCUDA.h" namespace clang { @@ -70,8 +71,8 @@ Sema::SemaDiagnosticBuilder SemaBase::Diag(SourceLocation Loc, unsigned DiagID, } SemaDiagnosticBuilder DB = getLangOpts().CUDAIsDevice - ? SemaRef.CUDADiagIfDeviceCode(Loc, DiagID) - : SemaRef.CUDADiagIfHostCode(Loc, DiagID); + ? SemaRef.CUDA().DiagIfDeviceCode(Loc, DiagID) + : SemaRef.CUDA().DiagIfHostCode(Loc, DiagID); SetIsLastErrorImmediate(DB.isImmediate()); return DB; } diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp index 4d4f4b6a2d4d95a6a1313266e71d1ea449ea0ff7..80ea43dc5316eb2932c4a339c8f3115edb1b6171 100644 --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -10,6 +10,7 @@ /// //===----------------------------------------------------------------------===// +#include "clang/Sema/SemaCUDA.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/ExprCXX.h" @@ -22,10 +23,13 @@ #include "clang/Sema/SemaDiagnostic.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallVector.h" #include using namespace clang; +SemaCUDA::SemaCUDA(Sema &S) : SemaBase(S) {} + template static bool hasExplicitAttr(const VarDecl *D) { if (!D) return false; @@ -34,38 +38,37 @@ template static bool hasExplicitAttr(const VarDecl *D) { return false; } -void Sema::PushForceCUDAHostDevice() { +void SemaCUDA::PushForceHostDevice() { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); - ForceCUDAHostDeviceDepth++; + ForceHostDeviceDepth++; } -bool Sema::PopForceCUDAHostDevice() { +bool SemaCUDA::PopForceHostDevice() { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); - if (ForceCUDAHostDeviceDepth == 0) + if (ForceHostDeviceDepth == 0) return false; - ForceCUDAHostDeviceDepth--; + ForceHostDeviceDepth--; return true; } -ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, +ExprResult SemaCUDA::ActOnExecConfigExpr(Scope *S, SourceLocation LLLLoc, MultiExprArg ExecConfig, SourceLocation GGGLoc) { - FunctionDecl *ConfigDecl = Context.getcudaConfigureCallDecl(); + FunctionDecl *ConfigDecl = getASTContext().getcudaConfigureCallDecl(); if (!ConfigDecl) return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use) - << getCudaConfigureFuncName()); + << getConfigureFuncName()); QualType ConfigQTy = ConfigDecl->getType(); - DeclRefExpr *ConfigDR = new (Context) - DeclRefExpr(Context, ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc); - MarkFunctionReferenced(LLLLoc, ConfigDecl); + DeclRefExpr *ConfigDR = new (getASTContext()) DeclRefExpr( + getASTContext(), ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc); + SemaRef.MarkFunctionReferenced(LLLLoc, ConfigDecl); - return BuildCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr, - /*IsExecConfig=*/true); + return SemaRef.BuildCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr, + /*IsExecConfig=*/true); } -Sema::CUDAFunctionTarget -Sema::IdentifyCUDATarget(const ParsedAttributesView &Attrs) { +CUDAFunctionTarget SemaCUDA::IdentifyTarget(const ParsedAttributesView &Attrs) { bool HasHostAttr = false; bool HasDeviceAttr = false; bool HasGlobalAttr = false; @@ -90,18 +93,18 @@ Sema::IdentifyCUDATarget(const ParsedAttributesView &Attrs) { } if (HasInvalidTargetAttr) - return CFT_InvalidTarget; + return CUDAFunctionTarget::InvalidTarget; if (HasGlobalAttr) - return CFT_Global; + return CUDAFunctionTarget::Global; if (HasHostAttr && HasDeviceAttr) - return CFT_HostDevice; + return CUDAFunctionTarget::HostDevice; if (HasDeviceAttr) - return CFT_Device; + return CUDAFunctionTarget::Device; - return CFT_Host; + return CUDAFunctionTarget::Host; } template @@ -112,55 +115,54 @@ static bool hasAttr(const Decl *D, bool IgnoreImplicitAttr) { }); } -Sema::CUDATargetContextRAII::CUDATargetContextRAII(Sema &S_, - CUDATargetContextKind K, - Decl *D) +SemaCUDA::CUDATargetContextRAII::CUDATargetContextRAII( + SemaCUDA &S_, SemaCUDA::CUDATargetContextKind K, Decl *D) : S(S_) { SavedCtx = S.CurCUDATargetCtx; - assert(K == CTCK_InitGlobalVar); + assert(K == SemaCUDA::CTCK_InitGlobalVar); auto *VD = dyn_cast_or_null(D); if (VD && VD->hasGlobalStorage() && !VD->isStaticLocal()) { - auto Target = CFT_Host; + auto Target = CUDAFunctionTarget::Host; if ((hasAttr(VD, /*IgnoreImplicit=*/true) && !hasAttr(VD, /*IgnoreImplicit=*/true)) || hasAttr(VD, /*IgnoreImplicit=*/true) || hasAttr(VD, /*IgnoreImplicit=*/true)) - Target = CFT_Device; + Target = CUDAFunctionTarget::Device; S.CurCUDATargetCtx = {Target, K, VD}; } } -/// IdentifyCUDATarget - Determine the CUDA compilation target for this function -Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D, - bool IgnoreImplicitHDAttr) { +/// IdentifyTarget - Determine the CUDA compilation target for this function +CUDAFunctionTarget SemaCUDA::IdentifyTarget(const FunctionDecl *D, + bool IgnoreImplicitHDAttr) { // Code that lives outside a function gets the target from CurCUDATargetCtx. if (D == nullptr) return CurCUDATargetCtx.Target; if (D->hasAttr()) - return CFT_InvalidTarget; + return CUDAFunctionTarget::InvalidTarget; if (D->hasAttr()) - return CFT_Global; + return CUDAFunctionTarget::Global; if (hasAttr(D, IgnoreImplicitHDAttr)) { if (hasAttr(D, IgnoreImplicitHDAttr)) - return CFT_HostDevice; - return CFT_Device; + return CUDAFunctionTarget::HostDevice; + return CUDAFunctionTarget::Device; } else if (hasAttr(D, IgnoreImplicitHDAttr)) { - return CFT_Host; + return CUDAFunctionTarget::Host; } else if ((D->isImplicit() || !D->isUserProvided()) && !IgnoreImplicitHDAttr) { // Some implicit declarations (like intrinsic functions) are not marked. // Set the most lenient target on them for maximal flexibility. - return CFT_HostDevice; + return CUDAFunctionTarget::HostDevice; } - return CFT_Host; + return CUDAFunctionTarget::Host; } /// IdentifyTarget - Determine the CUDA compilation target for this variable. -Sema::CUDAVariableTarget Sema::IdentifyCUDATarget(const VarDecl *Var) { +SemaCUDA::CUDAVariableTarget SemaCUDA::IdentifyTarget(const VarDecl *Var) { if (Var->hasAttr()) return CVT_Unified; // Only constexpr and const variabless with implicit constant attribute @@ -180,11 +182,11 @@ Sema::CUDAVariableTarget Sema::IdentifyCUDATarget(const VarDecl *Var) { // - on both sides in host device functions // - on device side in device or global functions if (auto *FD = dyn_cast(Var->getDeclContext())) { - switch (IdentifyCUDATarget(FD)) { - case CFT_HostDevice: + switch (IdentifyTarget(FD)) { + case CUDAFunctionTarget::HostDevice: return CVT_Both; - case CFT_Device: - case CFT_Global: + case CUDAFunctionTarget::Device: + case CUDAFunctionTarget::Global: return CVT_Device; default: return CVT_Host; @@ -221,58 +223,65 @@ Sema::CUDAVariableTarget Sema::IdentifyCUDATarget(const VarDecl *Var) { // | hd | h | SS | WS | (d) | // | hd | hd | HD | HD | (b) | -Sema::CUDAFunctionPreference -Sema::IdentifyCUDAPreference(const FunctionDecl *Caller, +SemaCUDA::CUDAFunctionPreference +SemaCUDA::IdentifyPreference(const FunctionDecl *Caller, const FunctionDecl *Callee) { assert(Callee && "Callee must be valid."); // Treat ctor/dtor as host device function in device var initializer to allow // trivial ctor/dtor without device attr to be used. Non-trivial ctor/dtor - // will be diagnosed by checkAllowedCUDAInitializer. + // will be diagnosed by checkAllowedInitializer. if (Caller == nullptr && CurCUDATargetCtx.Kind == CTCK_InitGlobalVar && - CurCUDATargetCtx.Target == CFT_Device && + CurCUDATargetCtx.Target == CUDAFunctionTarget::Device && (isa(Callee) || isa(Callee))) return CFP_HostDevice; - CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller); - CUDAFunctionTarget CalleeTarget = IdentifyCUDATarget(Callee); + CUDAFunctionTarget CallerTarget = IdentifyTarget(Caller); + CUDAFunctionTarget CalleeTarget = IdentifyTarget(Callee); // If one of the targets is invalid, the check always fails, no matter what // the other target is. - if (CallerTarget == CFT_InvalidTarget || CalleeTarget == CFT_InvalidTarget) + if (CallerTarget == CUDAFunctionTarget::InvalidTarget || + CalleeTarget == CUDAFunctionTarget::InvalidTarget) return CFP_Never; // (a) Can't call global from some contexts until we support CUDA's // dynamic parallelism. - if (CalleeTarget == CFT_Global && - (CallerTarget == CFT_Global || CallerTarget == CFT_Device)) + if (CalleeTarget == CUDAFunctionTarget::Global && + (CallerTarget == CUDAFunctionTarget::Global || + CallerTarget == CUDAFunctionTarget::Device)) return CFP_Never; // (b) Calling HostDevice is OK for everyone. - if (CalleeTarget == CFT_HostDevice) + if (CalleeTarget == CUDAFunctionTarget::HostDevice) return CFP_HostDevice; // (c) Best case scenarios if (CalleeTarget == CallerTarget || - (CallerTarget == CFT_Host && CalleeTarget == CFT_Global) || - (CallerTarget == CFT_Global && CalleeTarget == CFT_Device)) + (CallerTarget == CUDAFunctionTarget::Host && + CalleeTarget == CUDAFunctionTarget::Global) || + (CallerTarget == CUDAFunctionTarget::Global && + CalleeTarget == CUDAFunctionTarget::Device)) return CFP_Native; // HipStdPar mode is special, in that assessing whether a device side call to // a host target is deferred to a subsequent pass, and cannot unambiguously be // adjudicated in the AST, hence we optimistically allow them to pass here. if (getLangOpts().HIPStdPar && - (CallerTarget == CFT_Global || CallerTarget == CFT_Device || - CallerTarget == CFT_HostDevice) && - CalleeTarget == CFT_Host) + (CallerTarget == CUDAFunctionTarget::Global || + CallerTarget == CUDAFunctionTarget::Device || + CallerTarget == CUDAFunctionTarget::HostDevice) && + CalleeTarget == CUDAFunctionTarget::Host) return CFP_HostDevice; // (d) HostDevice behavior depends on compilation mode. - if (CallerTarget == CFT_HostDevice) { + if (CallerTarget == CUDAFunctionTarget::HostDevice) { // It's OK to call a compilation-mode matching function from an HD one. - if ((getLangOpts().CUDAIsDevice && CalleeTarget == CFT_Device) || + if ((getLangOpts().CUDAIsDevice && + CalleeTarget == CUDAFunctionTarget::Device) || (!getLangOpts().CUDAIsDevice && - (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global))) + (CalleeTarget == CUDAFunctionTarget::Host || + CalleeTarget == CUDAFunctionTarget::Global))) return CFP_SameSide; // Calls from HD to non-mode-matching functions (i.e., to host functions @@ -283,9 +292,12 @@ Sema::IdentifyCUDAPreference(const FunctionDecl *Caller, } // (e) Calling across device/host boundary is not something you should do. - if ((CallerTarget == CFT_Host && CalleeTarget == CFT_Device) || - (CallerTarget == CFT_Device && CalleeTarget == CFT_Host) || - (CallerTarget == CFT_Global && CalleeTarget == CFT_Host)) + if ((CallerTarget == CUDAFunctionTarget::Host && + CalleeTarget == CUDAFunctionTarget::Device) || + (CallerTarget == CUDAFunctionTarget::Device && + CalleeTarget == CUDAFunctionTarget::Host) || + (CallerTarget == CUDAFunctionTarget::Global && + CalleeTarget == CUDAFunctionTarget::Host)) return CFP_Never; llvm_unreachable("All cases should've been handled by now."); @@ -299,13 +311,13 @@ template static bool hasImplicitAttr(const FunctionDecl *D) { return D->isImplicit(); } -bool Sema::isCUDAImplicitHostDeviceFunction(const FunctionDecl *D) { +bool SemaCUDA::isImplicitHostDeviceFunction(const FunctionDecl *D) { bool IsImplicitDevAttr = hasImplicitAttr(D); bool IsImplicitHostAttr = hasImplicitAttr(D); return IsImplicitDevAttr && IsImplicitHostAttr; } -void Sema::EraseUnwantedCUDAMatches( +void SemaCUDA::EraseUnwantedMatches( const FunctionDecl *Caller, SmallVectorImpl> &Matches) { if (Matches.size() <= 1) @@ -315,7 +327,7 @@ void Sema::EraseUnwantedCUDAMatches( // Gets the CUDA function preference for a call from Caller to Match. auto GetCFP = [&](const Pair &Match) { - return IdentifyCUDAPreference(Caller, Match.second); + return IdentifyPreference(Caller, Match.second); }; // Find the best call preference among the functions in Matches. @@ -337,16 +349,16 @@ void Sema::EraseUnwantedCUDAMatches( /// \param ResolvedTarget with a target that resolves for both calls. /// \return true if there's a conflict, false otherwise. static bool -resolveCalleeCUDATargetConflict(Sema::CUDAFunctionTarget Target1, - Sema::CUDAFunctionTarget Target2, - Sema::CUDAFunctionTarget *ResolvedTarget) { +resolveCalleeCUDATargetConflict(CUDAFunctionTarget Target1, + CUDAFunctionTarget Target2, + CUDAFunctionTarget *ResolvedTarget) { // Only free functions and static member functions may be global. - assert(Target1 != Sema::CFT_Global); - assert(Target2 != Sema::CFT_Global); + assert(Target1 != CUDAFunctionTarget::Global); + assert(Target2 != CUDAFunctionTarget::Global); - if (Target1 == Sema::CFT_HostDevice) { + if (Target1 == CUDAFunctionTarget::HostDevice) { *ResolvedTarget = Target2; - } else if (Target2 == Sema::CFT_HostDevice) { + } else if (Target2 == CUDAFunctionTarget::HostDevice) { *ResolvedTarget = Target1; } else if (Target1 != Target2) { return true; @@ -357,8 +369,8 @@ resolveCalleeCUDATargetConflict(Sema::CUDAFunctionTarget Target1, return false; } -bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, - CXXSpecialMember CSM, +bool SemaCUDA::inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, + CXXSpecialMemberKind CSM, CXXMethodDecl *MemberDecl, bool ConstRHS, bool Diagnose) { @@ -378,7 +390,7 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, // We're going to invoke special member lookup; mark that these special // members are called from this one, and not from its caller. - ContextRAII MethodContext(*this, MemberDecl); + Sema::ContextRAII MethodContext(SemaRef, MemberDecl); // Look for special members in base classes that should be invoked from here. // Infer the target of this member base on the ones it should call. @@ -402,17 +414,17 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, CXXRecordDecl *BaseClassDecl = cast(BaseType->getDecl()); Sema::SpecialMemberOverloadResult SMOR = - LookupSpecialMember(BaseClassDecl, CSM, - /* ConstArg */ ConstRHS, - /* VolatileArg */ false, - /* RValueThis */ false, - /* ConstThis */ false, - /* VolatileThis */ false); + SemaRef.LookupSpecialMember(BaseClassDecl, CSM, + /* ConstArg */ ConstRHS, + /* VolatileArg */ false, + /* RValueThis */ false, + /* ConstThis */ false, + /* VolatileThis */ false); if (!SMOR.getMethod()) continue; - CUDAFunctionTarget BaseMethodTarget = IdentifyCUDATarget(SMOR.getMethod()); + CUDAFunctionTarget BaseMethodTarget = IdentifyTarget(SMOR.getMethod()); if (!InferredTarget) { InferredTarget = BaseMethodTarget; } else { @@ -422,9 +434,11 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, if (Diagnose) { Diag(ClassDecl->getLocation(), diag::note_implicit_member_target_infer_collision) - << (unsigned)CSM << *InferredTarget << BaseMethodTarget; + << (unsigned)CSM << llvm::to_underlying(*InferredTarget) + << llvm::to_underlying(BaseMethodTarget); } - MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context)); + MemberDecl->addAttr( + CUDAInvalidTargetAttr::CreateImplicit(getASTContext())); return true; } } @@ -437,25 +451,24 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, } const RecordType *FieldType = - Context.getBaseElementType(F->getType())->getAs(); + getASTContext().getBaseElementType(F->getType())->getAs(); if (!FieldType) { continue; } CXXRecordDecl *FieldRecDecl = cast(FieldType->getDecl()); Sema::SpecialMemberOverloadResult SMOR = - LookupSpecialMember(FieldRecDecl, CSM, - /* ConstArg */ ConstRHS && !F->isMutable(), - /* VolatileArg */ false, - /* RValueThis */ false, - /* ConstThis */ false, - /* VolatileThis */ false); + SemaRef.LookupSpecialMember(FieldRecDecl, CSM, + /* ConstArg */ ConstRHS && !F->isMutable(), + /* VolatileArg */ false, + /* RValueThis */ false, + /* ConstThis */ false, + /* VolatileThis */ false); if (!SMOR.getMethod()) continue; - CUDAFunctionTarget FieldMethodTarget = - IdentifyCUDATarget(SMOR.getMethod()); + CUDAFunctionTarget FieldMethodTarget = IdentifyTarget(SMOR.getMethod()); if (!InferredTarget) { InferredTarget = FieldMethodTarget; } else { @@ -465,9 +478,11 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, if (Diagnose) { Diag(ClassDecl->getLocation(), diag::note_implicit_member_target_infer_collision) - << (unsigned)CSM << *InferredTarget << FieldMethodTarget; + << (unsigned)CSM << llvm::to_underlying(*InferredTarget) + << llvm::to_underlying(FieldMethodTarget); } - MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context)); + MemberDecl->addAttr( + CUDAInvalidTargetAttr::CreateImplicit(getASTContext())); return true; } } @@ -478,25 +493,25 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, // it's the least restrictive option that can be invoked from any target. bool NeedsH = true, NeedsD = true; if (InferredTarget) { - if (*InferredTarget == CFT_Device) + if (*InferredTarget == CUDAFunctionTarget::Device) NeedsH = false; - else if (*InferredTarget == CFT_Host) + else if (*InferredTarget == CUDAFunctionTarget::Host) NeedsD = false; } // We either setting attributes first time, or the inferred ones must match // previously set ones. if (NeedsD && !HasD) - MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context)); + MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext())); if (NeedsH && !HasH) - MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context)); + MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(getASTContext())); return false; } -bool Sema::isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD) { +bool SemaCUDA::isEmptyConstructor(SourceLocation Loc, CXXConstructorDecl *CD) { if (!CD->isDefined() && CD->isTemplateInstantiation()) - InstantiateFunctionDefinition(Loc, CD->getFirstDecl()); + SemaRef.InstantiateFunctionDefinition(Loc, CD->getFirstDecl()); // (E.2.3.1, CUDA 7.5) A constructor for a class type is considered // empty at a point in the translation unit, if it is either a @@ -524,7 +539,7 @@ bool Sema::isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD) { if (!llvm::all_of(CD->inits(), [&](const CXXCtorInitializer *CI) { if (const CXXConstructExpr *CE = dyn_cast(CI->getInit())) - return isEmptyCudaConstructor(Loc, CE->getConstructor()); + return isEmptyConstructor(Loc, CE->getConstructor()); return false; })) return false; @@ -532,13 +547,13 @@ bool Sema::isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD) { return true; } -bool Sema::isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *DD) { +bool SemaCUDA::isEmptyDestructor(SourceLocation Loc, CXXDestructorDecl *DD) { // No destructor -> no problem. if (!DD) return true; if (!DD->isDefined() && DD->isTemplateInstantiation()) - InstantiateFunctionDefinition(Loc, DD->getFirstDecl()); + SemaRef.InstantiateFunctionDefinition(Loc, DD->getFirstDecl()); // (E.2.3.1, CUDA 7.5) A destructor for a class type is considered // empty at a point in the translation unit, if it is either a @@ -567,7 +582,7 @@ bool Sema::isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *DD) { // destructors for all base classes... if (!llvm::all_of(ClassDecl->bases(), [&](const CXXBaseSpecifier &BS) { if (CXXRecordDecl *RD = BS.getType()->getAsCXXRecordDecl()) - return isEmptyCudaDestructor(Loc, RD->getDestructor()); + return isEmptyDestructor(Loc, RD->getDestructor()); return true; })) return false; @@ -577,7 +592,7 @@ bool Sema::isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *DD) { if (CXXRecordDecl *RD = Field->getType() ->getBaseElementTypeUnsafe() ->getAsCXXRecordDecl()) - return isEmptyCudaDestructor(Loc, RD->getDestructor()); + return isEmptyDestructor(Loc, RD->getDestructor()); return true; })) return false; @@ -608,7 +623,7 @@ bool IsDependentVar(VarDecl *VD) { // __shared__ variables whether they are local or not (they all are implicitly // static in CUDA). One exception is that CUDA allows constant initializers // for __constant__ and __device__ variables. -bool HasAllowedCUDADeviceStaticInitializer(Sema &S, VarDecl *VD, +bool HasAllowedCUDADeviceStaticInitializer(SemaCUDA &S, VarDecl *VD, CUDAInitializerCheckKind CheckKind) { assert(!VD->isInvalidDecl() && VD->hasGlobalStorage()); assert(!IsDependentVar(VD) && "do not check dependent var"); @@ -617,30 +632,30 @@ bool HasAllowedCUDADeviceStaticInitializer(Sema &S, VarDecl *VD, if (!Init) return true; if (const auto *CE = dyn_cast(Init)) { - return S.isEmptyCudaConstructor(VD->getLocation(), CE->getConstructor()); + return S.isEmptyConstructor(VD->getLocation(), CE->getConstructor()); } return false; }; auto IsConstantInit = [&](const Expr *Init) { assert(Init); - ASTContext::CUDAConstantEvalContextRAII EvalCtx(S.Context, + ASTContext::CUDAConstantEvalContextRAII EvalCtx(S.getASTContext(), /*NoWronSidedVars=*/true); - return Init->isConstantInitializer(S.Context, + return Init->isConstantInitializer(S.getASTContext(), VD->getType()->isReferenceType()); }; auto HasEmptyDtor = [&](VarDecl *VD) { if (const auto *RD = VD->getType()->getAsCXXRecordDecl()) - return S.isEmptyCudaDestructor(VD->getLocation(), RD->getDestructor()); + return S.isEmptyDestructor(VD->getLocation(), RD->getDestructor()); return true; }; if (CheckKind == CICK_Shared) return IsEmptyInit(Init) && HasEmptyDtor(VD); - return S.LangOpts.GPUAllowDeviceInit || + return S.getLangOpts().GPUAllowDeviceInit || ((IsEmptyInit(Init) || IsConstantInit(Init)) && HasEmptyDtor(VD)); } } // namespace -void Sema::checkAllowedCUDAInitializer(VarDecl *VD) { +void SemaCUDA::checkAllowedInitializer(VarDecl *VD) { // Return early if VD is inside a non-instantiated template function since // the implicit constructor is not defined yet. if (const FunctionDecl *FD = @@ -676,10 +691,11 @@ void Sema::checkAllowedCUDAInitializer(VarDecl *VD) { InitFn = CE->getDirectCallee(); } if (InitFn) { - CUDAFunctionTarget InitFnTarget = IdentifyCUDATarget(InitFn); - if (InitFnTarget != CFT_Host && InitFnTarget != CFT_HostDevice) { + CUDAFunctionTarget InitFnTarget = IdentifyTarget(InitFn); + if (InitFnTarget != CUDAFunctionTarget::Host && + InitFnTarget != CUDAFunctionTarget::HostDevice) { Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer) - << InitFnTarget << InitFn; + << llvm::to_underlying(InitFnTarget) << InitFn; Diag(InitFn->getLocation(), diag::note_previous_decl) << InitFn; VD->setInvalidDecl(); } @@ -687,21 +703,22 @@ void Sema::checkAllowedCUDAInitializer(VarDecl *VD) { } } -void Sema::CUDARecordImplicitHostDeviceFuncUsedByDevice( +void SemaCUDA::RecordImplicitHostDeviceFuncUsedByDevice( const FunctionDecl *Callee) { - FunctionDecl *Caller = getCurFunctionDecl(/*AllowLambda=*/true); + FunctionDecl *Caller = SemaRef.getCurFunctionDecl(/*AllowLambda=*/true); if (!Caller) return; - if (!isCUDAImplicitHostDeviceFunction(Callee)) + if (!isImplicitHostDeviceFunction(Callee)) return; - CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller); + CUDAFunctionTarget CallerTarget = IdentifyTarget(Caller); // Record whether an implicit host device function is used on device side. - if (CallerTarget != CFT_Device && CallerTarget != CFT_Global && - (CallerTarget != CFT_HostDevice || - (isCUDAImplicitHostDeviceFunction(Caller) && + if (CallerTarget != CUDAFunctionTarget::Device && + CallerTarget != CUDAFunctionTarget::Global && + (CallerTarget != CUDAFunctionTarget::HostDevice || + (isImplicitHostDeviceFunction(Caller) && !getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(Caller)))) return; @@ -717,18 +734,18 @@ void Sema::CUDARecordImplicitHostDeviceFuncUsedByDevice( // system header, in which case we leave the constexpr function unattributed. // // In addition, all function decls are treated as __host__ __device__ when -// ForceCUDAHostDeviceDepth > 0 (corresponding to code within a +// ForceHostDeviceDepth > 0 (corresponding to code within a // #pragma clang force_cuda_host_device_begin/end // pair). -void Sema::maybeAddCUDAHostDeviceAttrs(FunctionDecl *NewD, +void SemaCUDA::maybeAddHostDeviceAttrs(FunctionDecl *NewD, const LookupResult &Previous) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); - if (ForceCUDAHostDeviceDepth > 0) { + if (ForceHostDeviceDepth > 0) { if (!NewD->hasAttr()) - NewD->addAttr(CUDAHostAttr::CreateImplicit(Context)); + NewD->addAttr(CUDAHostAttr::CreateImplicit(getASTContext())); if (!NewD->hasAttr()) - NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context)); + NewD->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext())); return; } @@ -739,8 +756,8 @@ void Sema::maybeAddCUDAHostDeviceAttrs(FunctionDecl *NewD, !NewD->hasAttr() && (NewD->getDescribedFunctionTemplate() || NewD->isFunctionTemplateSpecialization())) { - NewD->addAttr(CUDAHostAttr::CreateImplicit(Context)); - NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context)); + NewD->addAttr(CUDAHostAttr::CreateImplicit(getASTContext())); + NewD->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext())); return; } @@ -757,8 +774,9 @@ void Sema::maybeAddCUDAHostDeviceAttrs(FunctionDecl *NewD, FunctionDecl *OldD = D->getAsFunction(); return OldD && OldD->hasAttr() && !OldD->hasAttr() && - !IsOverload(NewD, OldD, /* UseMemberUsingDeclRules = */ false, - /* ConsiderCudaAttrs = */ false); + !SemaRef.IsOverload(NewD, OldD, + /* UseMemberUsingDeclRules = */ false, + /* ConsiderCudaAttrs = */ false); }; auto It = llvm::find_if(Previous, IsMatchingDeviceFn); if (It != Previous.end()) { @@ -767,7 +785,7 @@ void Sema::maybeAddCUDAHostDeviceAttrs(FunctionDecl *NewD, // in a system header, in which case we simply return without making NewD // host+device. NamedDecl *Match = *It; - if (!getSourceManager().isInSystemHeader(Match->getLocation())) { + if (!SemaRef.getSourceManager().isInSystemHeader(Match->getLocation())) { Diag(NewD->getLocation(), diag::err_cuda_unattributed_constexpr_cannot_overload_device) << NewD; @@ -777,14 +795,14 @@ void Sema::maybeAddCUDAHostDeviceAttrs(FunctionDecl *NewD, return; } - NewD->addAttr(CUDAHostAttr::CreateImplicit(Context)); - NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context)); + NewD->addAttr(CUDAHostAttr::CreateImplicit(getASTContext())); + NewD->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext())); } // TODO: `__constant__` memory may be a limited resource for certain targets. // A safeguard may be needed at the end of compilation pipeline if // `__constant__` memory usage goes beyond limit. -void Sema::MaybeAddCUDAConstantAttr(VarDecl *VD) { +void SemaCUDA::MaybeAddConstantAttr(VarDecl *VD) { // Do not promote dependent variables since the cotr/dtor/initializer are // not determined. Do it after instantiation. if (getLangOpts().CUDAIsDevice && !VD->hasAttr() && @@ -798,86 +816,90 @@ void Sema::MaybeAddCUDAConstantAttr(VarDecl *VD) { } } -Sema::SemaDiagnosticBuilder Sema::CUDADiagIfDeviceCode(SourceLocation Loc, - unsigned DiagID) { +SemaBase::SemaDiagnosticBuilder SemaCUDA::DiagIfDeviceCode(SourceLocation Loc, + unsigned DiagID) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); - FunctionDecl *CurFunContext = getCurFunctionDecl(/*AllowLambda=*/true); + FunctionDecl *CurFunContext = + SemaRef.getCurFunctionDecl(/*AllowLambda=*/true); SemaDiagnosticBuilder::Kind DiagKind = [&] { if (!CurFunContext) return SemaDiagnosticBuilder::K_Nop; - switch (CurrentCUDATarget()) { - case CFT_Global: - case CFT_Device: + switch (CurrentTarget()) { + case CUDAFunctionTarget::Global: + case CUDAFunctionTarget::Device: return SemaDiagnosticBuilder::K_Immediate; - case CFT_HostDevice: + case CUDAFunctionTarget::HostDevice: // An HD function counts as host code if we're compiling for host, and // device code if we're compiling for device. Defer any errors in device // mode until the function is known-emitted. if (!getLangOpts().CUDAIsDevice) return SemaDiagnosticBuilder::K_Nop; - if (IsLastErrorImmediate && Diags.getDiagnosticIDs()->isBuiltinNote(DiagID)) + if (SemaRef.IsLastErrorImmediate && + getDiagnostics().getDiagnosticIDs()->isBuiltinNote(DiagID)) return SemaDiagnosticBuilder::K_Immediate; - return (getEmissionStatus(CurFunContext) == - FunctionEmissionStatus::Emitted) + return (SemaRef.getEmissionStatus(CurFunContext) == + Sema::FunctionEmissionStatus::Emitted) ? SemaDiagnosticBuilder::K_ImmediateWithCallStack : SemaDiagnosticBuilder::K_Deferred; default: return SemaDiagnosticBuilder::K_Nop; } }(); - return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, CurFunContext, *this); + return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, CurFunContext, SemaRef); } -Sema::SemaDiagnosticBuilder Sema::CUDADiagIfHostCode(SourceLocation Loc, +Sema::SemaDiagnosticBuilder SemaCUDA::DiagIfHostCode(SourceLocation Loc, unsigned DiagID) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); - FunctionDecl *CurFunContext = getCurFunctionDecl(/*AllowLambda=*/true); + FunctionDecl *CurFunContext = + SemaRef.getCurFunctionDecl(/*AllowLambda=*/true); SemaDiagnosticBuilder::Kind DiagKind = [&] { if (!CurFunContext) return SemaDiagnosticBuilder::K_Nop; - switch (CurrentCUDATarget()) { - case CFT_Host: + switch (CurrentTarget()) { + case CUDAFunctionTarget::Host: return SemaDiagnosticBuilder::K_Immediate; - case CFT_HostDevice: + case CUDAFunctionTarget::HostDevice: // An HD function counts as host code if we're compiling for host, and // device code if we're compiling for device. Defer any errors in device // mode until the function is known-emitted. if (getLangOpts().CUDAIsDevice) return SemaDiagnosticBuilder::K_Nop; - if (IsLastErrorImmediate && Diags.getDiagnosticIDs()->isBuiltinNote(DiagID)) + if (SemaRef.IsLastErrorImmediate && + getDiagnostics().getDiagnosticIDs()->isBuiltinNote(DiagID)) return SemaDiagnosticBuilder::K_Immediate; - return (getEmissionStatus(CurFunContext) == - FunctionEmissionStatus::Emitted) + return (SemaRef.getEmissionStatus(CurFunContext) == + Sema::FunctionEmissionStatus::Emitted) ? SemaDiagnosticBuilder::K_ImmediateWithCallStack : SemaDiagnosticBuilder::K_Deferred; default: return SemaDiagnosticBuilder::K_Nop; } }(); - return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, CurFunContext, *this); + return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, CurFunContext, SemaRef); } -bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { +bool SemaCUDA::CheckCall(SourceLocation Loc, FunctionDecl *Callee) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); assert(Callee && "Callee may not be null."); - const auto &ExprEvalCtx = currentEvaluationContext(); + const auto &ExprEvalCtx = SemaRef.currentEvaluationContext(); if (ExprEvalCtx.isUnevaluated() || ExprEvalCtx.isConstantEvaluated()) return true; // FIXME: Is bailing out early correct here? Should we instead assume that // the caller is a global initializer? - FunctionDecl *Caller = getCurFunctionDecl(/*AllowLambda=*/true); + FunctionDecl *Caller = SemaRef.getCurFunctionDecl(/*AllowLambda=*/true); if (!Caller) return true; // If the caller is known-emitted, mark the callee as known-emitted. // Otherwise, mark the call in our call graph so we can traverse it later. - bool CallerKnownEmitted = - getEmissionStatus(Caller) == FunctionEmissionStatus::Emitted; + bool CallerKnownEmitted = SemaRef.getEmissionStatus(Caller) == + Sema::FunctionEmissionStatus::Emitted; SemaDiagnosticBuilder::Kind DiagKind = [this, Caller, Callee, CallerKnownEmitted] { - switch (IdentifyCUDAPreference(Caller, Callee)) { + switch (IdentifyPreference(Caller, Callee)) { case CFP_Never: case CFP_WrongSide: assert(Caller && "Never/wrongSide calls require a non-null caller"); @@ -894,7 +916,7 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { if (DiagKind == SemaDiagnosticBuilder::K_Nop) { // For -fgpu-rdc, keep track of external kernels used by host functions. - if (LangOpts.CUDAIsDevice && LangOpts.GPURelocatableDeviceCode && + if (getLangOpts().CUDAIsDevice && getLangOpts().GPURelocatableDeviceCode && Callee->hasAttr() && !Callee->isDefined() && (!Caller || (!Caller->getDescribedFunctionTemplate() && getASTContext().GetGVALinkageForFunction(Caller) == @@ -910,12 +932,13 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { if (!LocsWithCUDACallDiags.insert({Caller, Loc}).second) return true; - SemaDiagnosticBuilder(DiagKind, Loc, diag::err_ref_bad_target, Caller, *this) - << IdentifyCUDATarget(Callee) << /*function*/ 0 << Callee - << IdentifyCUDATarget(Caller); + SemaDiagnosticBuilder(DiagKind, Loc, diag::err_ref_bad_target, Caller, + SemaRef) + << llvm::to_underlying(IdentifyTarget(Callee)) << /*function*/ 0 << Callee + << llvm::to_underlying(IdentifyTarget(Caller)); if (!Callee->getBuiltinID()) SemaDiagnosticBuilder(DiagKind, Callee->getLocation(), - diag::note_previous_decl, Caller, *this) + diag::note_previous_decl, Caller, SemaRef) << Callee; return DiagKind != SemaDiagnosticBuilder::K_Immediate && DiagKind != SemaDiagnosticBuilder::K_ImmediateWithCallStack; @@ -926,7 +949,7 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { // defined and uses the capture by reference when the lambda is called. When // the capture and use happen on different sides, the capture is invalid and // should be diagnosed. -void Sema::CUDACheckLambdaCapture(CXXMethodDecl *Callee, +void SemaCUDA::CheckLambdaCapture(CXXMethodDecl *Callee, const sema::Capture &Capture) { // In host compilation we only need to check lambda functions emitted on host // side. In such lambda functions, a reference capture is invalid only @@ -936,12 +959,12 @@ void Sema::CUDACheckLambdaCapture(CXXMethodDecl *Callee, // kernel cannot pass a lambda back to a host function since we cannot // define a kernel argument type which can hold the lambda before the lambda // itself is defined. - if (!LangOpts.CUDAIsDevice) + if (!getLangOpts().CUDAIsDevice) return; // File-scope lambda can only do init captures for global variables, which // results in passing by value for these global variables. - FunctionDecl *Caller = getCurFunctionDecl(/*AllowLambda=*/true); + FunctionDecl *Caller = SemaRef.getCurFunctionDecl(/*AllowLambda=*/true); if (!Caller) return; @@ -958,7 +981,7 @@ void Sema::CUDACheckLambdaCapture(CXXMethodDecl *Callee, auto DiagKind = SemaDiagnosticBuilder::K_Deferred; if (Capture.isVariableCapture() && !getLangOpts().HIPStdPar) { SemaDiagnosticBuilder(DiagKind, Capture.getLocation(), - diag::err_capture_bad_target, Callee, *this) + diag::err_capture_bad_target, Callee, SemaRef) << Capture.getVariable(); } else if (Capture.isThisCapture()) { // Capture of this pointer is allowed since this pointer may be pointing to @@ -967,47 +990,49 @@ void Sema::CUDACheckLambdaCapture(CXXMethodDecl *Callee, // accessible on device side. SemaDiagnosticBuilder(DiagKind, Capture.getLocation(), diag::warn_maybe_capture_bad_target_this_ptr, Callee, - *this); + SemaRef); } } -void Sema::CUDASetLambdaAttrs(CXXMethodDecl *Method) { +void SemaCUDA::SetLambdaAttrs(CXXMethodDecl *Method) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); if (Method->hasAttr() || Method->hasAttr()) return; - Method->addAttr(CUDADeviceAttr::CreateImplicit(Context)); - Method->addAttr(CUDAHostAttr::CreateImplicit(Context)); + Method->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext())); + Method->addAttr(CUDAHostAttr::CreateImplicit(getASTContext())); } -void Sema::checkCUDATargetOverload(FunctionDecl *NewFD, +void SemaCUDA::checkTargetOverload(FunctionDecl *NewFD, const LookupResult &Previous) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); - CUDAFunctionTarget NewTarget = IdentifyCUDATarget(NewFD); + CUDAFunctionTarget NewTarget = IdentifyTarget(NewFD); for (NamedDecl *OldND : Previous) { FunctionDecl *OldFD = OldND->getAsFunction(); if (!OldFD) continue; - CUDAFunctionTarget OldTarget = IdentifyCUDATarget(OldFD); + CUDAFunctionTarget OldTarget = IdentifyTarget(OldFD); // Don't allow HD and global functions to overload other functions with the // same signature. We allow overloading based on CUDA attributes so that // functions can have different implementations on the host and device, but // HD/global functions "exist" in some sense on both the host and device, so // should have the same implementation on both sides. if (NewTarget != OldTarget && - ((NewTarget == CFT_HostDevice && - !(LangOpts.OffloadImplicitHostDeviceTemplates && - isCUDAImplicitHostDeviceFunction(NewFD) && - OldTarget == CFT_Device)) || - (OldTarget == CFT_HostDevice && - !(LangOpts.OffloadImplicitHostDeviceTemplates && - isCUDAImplicitHostDeviceFunction(OldFD) && - NewTarget == CFT_Device)) || - (NewTarget == CFT_Global) || (OldTarget == CFT_Global)) && - !IsOverload(NewFD, OldFD, /* UseMemberUsingDeclRules = */ false, - /* ConsiderCudaAttrs = */ false)) { + ((NewTarget == CUDAFunctionTarget::HostDevice && + !(getLangOpts().OffloadImplicitHostDeviceTemplates && + isImplicitHostDeviceFunction(NewFD) && + OldTarget == CUDAFunctionTarget::Device)) || + (OldTarget == CUDAFunctionTarget::HostDevice && + !(getLangOpts().OffloadImplicitHostDeviceTemplates && + isImplicitHostDeviceFunction(OldFD) && + NewTarget == CUDAFunctionTarget::Device)) || + (NewTarget == CUDAFunctionTarget::Global) || + (OldTarget == CUDAFunctionTarget::Global)) && + !SemaRef.IsOverload(NewFD, OldFD, /* UseMemberUsingDeclRules = */ false, + /* ConsiderCudaAttrs = */ false)) { Diag(NewFD->getLocation(), diag::err_cuda_ovl_target) - << NewTarget << NewFD->getDeclName() << OldTarget << OldFD; + << llvm::to_underlying(NewTarget) << NewFD->getDeclName() + << llvm::to_underlying(OldTarget) << OldFD; Diag(OldFD->getLocation(), diag::note_previous_declaration); NewFD->setInvalidDecl(); break; @@ -1025,21 +1050,21 @@ static void copyAttrIfPresent(Sema &S, FunctionDecl *FD, } } -void Sema::inheritCUDATargetAttrs(FunctionDecl *FD, +void SemaCUDA::inheritTargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD) { const FunctionDecl &TemplateFD = *TD.getTemplatedDecl(); - copyAttrIfPresent(*this, FD, TemplateFD); - copyAttrIfPresent(*this, FD, TemplateFD); - copyAttrIfPresent(*this, FD, TemplateFD); + copyAttrIfPresent(SemaRef, FD, TemplateFD); + copyAttrIfPresent(SemaRef, FD, TemplateFD); + copyAttrIfPresent(SemaRef, FD, TemplateFD); } -std::string Sema::getCudaConfigureFuncName() const { +std::string SemaCUDA::getConfigureFuncName() const { if (getLangOpts().HIP) return getLangOpts().HIPUseNewLaunchAPI ? "__hipPushCallConfiguration" : "hipConfigureCall"; // New CUDA kernel launch sequence. - if (CudaFeatureEnabled(Context.getTargetInfo().getSDKVersion(), + if (CudaFeatureEnabled(getASTContext().getTargetInfo().getSDKVersion(), CudaFeature::CUDA_USES_NEW_LAUNCH)) return "__cudaPushCallConfiguration"; diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 9d85568d97b2d27936b6b94c45b1546bf22cfa4e..b0c28531fe873854a9502347362c014271ebb66a 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -498,10 +498,22 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT, howManyCandidates = OCD_AmbiguousCandidates; break; - case OR_Deleted: - msg = diag::err_ovl_deleted_conversion_in_cast; - howManyCandidates = OCD_ViableCandidates; - break; + case OR_Deleted: { + OverloadCandidateSet::iterator Best; + [[maybe_unused]] OverloadingResult Res = + candidates.BestViableFunction(S, range.getBegin(), Best); + assert(Res == OR_Deleted && "Inconsistent overload resolution"); + + StringLiteral *Msg = Best->Function->getDeletedMessage(); + candidates.NoteCandidates( + PartialDiagnosticAt(range.getBegin(), + S.PDiag(diag::err_ovl_deleted_conversion_in_cast) + << CT << srcType << destType << (Msg != nullptr) + << (Msg ? Msg->getString() : StringRef()) + << range << src->getSourceRange()), + S, OCD_ViableCandidates, src); + return true; + } } candidates.NoteCandidates( diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index abfd9a3031577bb0616c458894caeb27a7c43197..8e21811b67d900d7ca72fc2c99adc045e4acf3df 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -19710,6 +19710,27 @@ bool Sema::IsLayoutCompatible(QualType T1, QualType T2) const { return isLayoutCompatible(getASTContext(), T1, T2); } +//===-------------- Pointer interconvertibility ----------------------------// + +bool Sema::IsPointerInterconvertibleBaseOf(const TypeSourceInfo *Base, + const TypeSourceInfo *Derived) { + QualType BaseT = Base->getType()->getCanonicalTypeUnqualified(); + QualType DerivedT = Derived->getType()->getCanonicalTypeUnqualified(); + + if (BaseT->isStructureOrClassType() && DerivedT->isStructureOrClassType() && + getASTContext().hasSameType(BaseT, DerivedT)) + return true; + + if (!IsDerivedFrom(Derived->getTypeLoc().getBeginLoc(), DerivedT, BaseT)) + return false; + + // Per [basic.compound]/4.3, containing object has to be standard-layout. + if (DerivedT->getAsCXXRecordDecl()->isStandardLayout()) + return true; + + return false; +} + //===--- CHECK: pointer_with_type_tag attribute: datatypes should match ----// /// Given a type tag expression find the type tag itself. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a4699d6ba2c735b944436f062a73d696fa807b56..8b3b9d020db5723aeb100b183f94016572761acb 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -45,8 +45,11 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" +#include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/TargetParser/Triple.h" @@ -2972,10 +2975,10 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, else if (const auto *BTFA = dyn_cast(Attr)) NewAttr = S.mergeBTFDeclTagAttr(D, *BTFA); else if (const auto *NT = dyn_cast(Attr)) - NewAttr = - S.mergeHLSLNumThreadsAttr(D, *NT, NT->getX(), NT->getY(), NT->getZ()); + NewAttr = S.HLSL().mergeNumThreadsAttr(D, *NT, NT->getX(), NT->getY(), + NT->getZ()); else if (const auto *SA = dyn_cast(Attr)) - NewAttr = S.mergeHLSLShaderAttr(D, *SA, SA->getType()); + NewAttr = S.HLSL().mergeShaderAttr(D, *SA, SA->getType()); else if (isa(Attr)) // Do nothing. Each redeclaration should be suppressed separately. NewAttr = nullptr; @@ -4048,13 +4051,13 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S, } else { Diag(NewMethod->getLocation(), diag::err_definition_of_implicitly_declared_member) - << New << getSpecialMember(OldMethod); + << New << llvm::to_underlying(getSpecialMember(OldMethod)); return true; } } else if (OldMethod->getFirstDecl()->isExplicitlyDefaulted() && !isFriend) { Diag(NewMethod->getLocation(), diag::err_definition_of_explicitly_defaulted_member) - << getSpecialMember(OldMethod); + << llvm::to_underlying(getSpecialMember(OldMethod)); return true; } } @@ -10593,12 +10596,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // We do not add HD attributes to specializations here because // they may have different constexpr-ness compared to their - // templates and, after maybeAddCUDAHostDeviceAttrs() is applied, + // templates and, after maybeAddHostDeviceAttrs() is applied, // may end up with different effective targets. Instead, a // specialization inherits its target attributes from its template // in the CheckFunctionTemplateSpecialization() call below. if (getLangOpts().CUDA && !isFunctionTemplateSpecialization) - maybeAddCUDAHostDeviceAttrs(NewFD, Previous); + CUDA().maybeAddHostDeviceAttrs(NewFD, Previous); // Handle explict specializations of function templates // and friend function declarations with an explicit @@ -10808,10 +10811,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (getLangOpts().HLSL && D.isFunctionDefinition()) { // Any top level function could potentially be specified as an entry. if (!NewFD->isInvalidDecl() && S->getDepth() == 0 && Name.isIdentifier()) - ActOnHLSLTopLevelFunction(NewFD); + HLSL().ActOnTopLevelFunction(NewFD); if (NewFD->hasAttr()) - CheckHLSLEntryPoint(NewFD); + HLSL().CheckEntryPoint(NewFD); } // If this is the first declaration of a library builtin function, add @@ -10896,12 +10899,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (getLangOpts().CUDA) { IdentifierInfo *II = NewFD->getIdentifier(); - if (II && II->isStr(getCudaConfigureFuncName()) && + if (II && II->isStr(CUDA().getConfigureFuncName()) && !NewFD->isInvalidDecl() && NewFD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { if (!R->castAs()->getReturnType()->isScalarType()) Diag(NewFD->getLocation(), diag::err_config_scalar_return) - << getCudaConfigureFuncName(); + << CUDA().getConfigureFuncName(); Context.setcudaConfigureCallDecl(NewFD); } @@ -11911,8 +11914,14 @@ 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 && S.getASTContext().getTargetInfo().getTriple().isAArch64()) + if (NewTA && T.isAArch64()) + return false; + + // Target attribute on RISCV is not used for multiversioning + if (NewTA && T.isRISCV()) return false; if (!OldDecl || !OldDecl->getAsFunction() || @@ -12390,7 +12399,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } if (!Redeclaration && LangOpts.CUDA) - checkCUDATargetOverload(NewFD, Previous); + CUDA().checkTargetOverload(NewFD, Previous); } // Check if the function definition uses any AArch64 SME features without @@ -12659,125 +12668,6 @@ void Sema::CheckMSVCRTEntryPoint(FunctionDecl *FD) { } } -void Sema::ActOnHLSLTopLevelFunction(FunctionDecl *FD) { - auto &TargetInfo = getASTContext().getTargetInfo(); - - if (FD->getName() != TargetInfo.getTargetOpts().HLSLEntry) - return; - - StringRef Env = TargetInfo.getTriple().getEnvironmentName(); - HLSLShaderAttr::ShaderType ShaderType; - if (HLSLShaderAttr::ConvertStrToShaderType(Env, ShaderType)) { - if (const auto *Shader = FD->getAttr()) { - // The entry point is already annotated - check that it matches the - // triple. - if (Shader->getType() != ShaderType) { - Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch) - << Shader; - FD->setInvalidDecl(); - } - } else { - // Implicitly add the shader attribute if the entry function isn't - // explicitly annotated. - FD->addAttr(HLSLShaderAttr::CreateImplicit(Context, ShaderType, - FD->getBeginLoc())); - } - } else { - switch (TargetInfo.getTriple().getEnvironment()) { - case llvm::Triple::UnknownEnvironment: - case llvm::Triple::Library: - break; - default: - llvm_unreachable("Unhandled environment in triple"); - } - } -} - -void Sema::CheckHLSLEntryPoint(FunctionDecl *FD) { - const auto *ShaderAttr = FD->getAttr(); - assert(ShaderAttr && "Entry point has no shader attribute"); - HLSLShaderAttr::ShaderType ST = ShaderAttr->getType(); - - switch (ST) { - case HLSLShaderAttr::Pixel: - case HLSLShaderAttr::Vertex: - case HLSLShaderAttr::Geometry: - case HLSLShaderAttr::Hull: - case HLSLShaderAttr::Domain: - case HLSLShaderAttr::RayGeneration: - case HLSLShaderAttr::Intersection: - case HLSLShaderAttr::AnyHit: - case HLSLShaderAttr::ClosestHit: - case HLSLShaderAttr::Miss: - case HLSLShaderAttr::Callable: - if (const auto *NT = FD->getAttr()) { - DiagnoseHLSLAttrStageMismatch(NT, ST, - {HLSLShaderAttr::Compute, - HLSLShaderAttr::Amplification, - HLSLShaderAttr::Mesh}); - FD->setInvalidDecl(); - } - break; - - case HLSLShaderAttr::Compute: - case HLSLShaderAttr::Amplification: - case HLSLShaderAttr::Mesh: - if (!FD->hasAttr()) { - Diag(FD->getLocation(), diag::err_hlsl_missing_numthreads) - << HLSLShaderAttr::ConvertShaderTypeToStr(ST); - FD->setInvalidDecl(); - } - break; - } - - for (ParmVarDecl *Param : FD->parameters()) { - if (const auto *AnnotationAttr = Param->getAttr()) { - CheckHLSLSemanticAnnotation(FD, Param, AnnotationAttr); - } else { - // FIXME: Handle struct parameters where annotations are on struct fields. - // See: https://github.com/llvm/llvm-project/issues/57875 - Diag(FD->getLocation(), diag::err_hlsl_missing_semantic_annotation); - Diag(Param->getLocation(), diag::note_previous_decl) << Param; - FD->setInvalidDecl(); - } - } - // FIXME: Verify return type semantic annotation. -} - -void Sema::CheckHLSLSemanticAnnotation( - FunctionDecl *EntryPoint, const Decl *Param, - const HLSLAnnotationAttr *AnnotationAttr) { - auto *ShaderAttr = EntryPoint->getAttr(); - assert(ShaderAttr && "Entry point has no shader attribute"); - HLSLShaderAttr::ShaderType ST = ShaderAttr->getType(); - - switch (AnnotationAttr->getKind()) { - case attr::HLSLSV_DispatchThreadID: - case attr::HLSLSV_GroupIndex: - if (ST == HLSLShaderAttr::Compute) - return; - DiagnoseHLSLAttrStageMismatch(AnnotationAttr, ST, - {HLSLShaderAttr::Compute}); - break; - default: - llvm_unreachable("Unknown HLSLAnnotationAttr"); - } -} - -void Sema::DiagnoseHLSLAttrStageMismatch( - const Attr *A, HLSLShaderAttr::ShaderType Stage, - std::initializer_list AllowedStages) { - SmallVector StageStrings; - llvm::transform(AllowedStages, std::back_inserter(StageStrings), - [](HLSLShaderAttr::ShaderType ST) { - return StringRef( - HLSLShaderAttr::ConvertShaderTypeToStr(ST)); - }); - Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage) - << A << HLSLShaderAttr::ConvertShaderTypeToStr(Stage) - << (AllowedStages.size() != 1) << join(StageStrings, ", "); -} - bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) { // FIXME: Need strict checking. In C89, we need to check for // any assignment, increment, decrement, function-calls, or @@ -14526,7 +14416,7 @@ StmtResult Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc, void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { if (var->isInvalidDecl()) return; - MaybeAddCUDAConstantAttr(var); + CUDA().MaybeAddConstantAttr(var); if (getLangOpts().OpenCL) { // OpenCL v2.0 s6.12.5 - Every block variable declaration must have an @@ -14940,7 +14830,7 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) { // variables whether they are local or not. CUDA also allows // constant initializers for __constant__ and __device__ variables. if (getLangOpts().CUDA) - checkAllowedCUDAInitializer(VD); + CUDA().checkAllowedInitializer(VD); // Grab the dllimport or dllexport attribute off of the VarDecl. const InheritableAttr *DLLAttr = getDLLAttr(VD); @@ -16193,7 +16083,17 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // This is meant to pop the context added in ActOnStartOfFunctionDef(). ExitFunctionBodyRAII ExitRAII(*this, isLambdaCallOperator(FD)); if (FD) { - FD->setBody(Body); + // If this is called by Parser::ParseFunctionDefinition() after marking + // the declaration as deleted, and if the deleted-function-body contains + // a message (C++26), then a DefaultedOrDeletedInfo will have already been + // added to store that message; do not overwrite it in that case. + // + // Since this would always set the body to 'nullptr' in that case anyway, + // which is already done when the function decl is initially created, + // always skipping this irrespective of whether there is a delete message + // should not be a problem. + if (!FD->isDeletedAsWritten()) + FD->setBody(Body); FD->setWillHaveBody(false); CheckImmediateEscalatingFunctionDefinition(FD, FSI); @@ -18959,22 +18859,22 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { // because otherwise we'll never get complaints about // copy constructors. - CXXSpecialMember member = CXXInvalid; + CXXSpecialMemberKind member = CXXSpecialMemberKind::Invalid; // We're required to check for any non-trivial constructors. Since the // implicit default constructor is suppressed if there are any // user-declared constructors, we just need to check that there is a // trivial default constructor and a trivial copy constructor. (We don't // worry about move constructors here, since this is a C++98 check.) if (RDecl->hasNonTrivialCopyConstructor()) - member = CXXCopyConstructor; + member = CXXSpecialMemberKind::CopyConstructor; else if (!RDecl->hasTrivialDefaultConstructor()) - member = CXXDefaultConstructor; + member = CXXSpecialMemberKind::DefaultConstructor; else if (RDecl->hasNonTrivialCopyAssignment()) - member = CXXCopyAssignment; + member = CXXSpecialMemberKind::CopyAssignment; else if (RDecl->hasNonTrivialDestructor()) - member = CXXDestructor; + member = CXXSpecialMemberKind::Destructor; - if (member != CXXInvalid) { + if (member != CXXSpecialMemberKind::Invalid) { if (!getLangOpts().CPlusPlus11 && getLangOpts().ObjCAutoRefCount && RDecl->hasObjectMember()) { // Objective-C++ ARC: it is an error to have a non-trivial field of @@ -18991,10 +18891,13 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { } } - Diag(FD->getLocation(), getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member : - diag::err_illegal_union_or_anon_struct_member) - << FD->getParent()->isUnion() << FD->getDeclName() << member; + Diag( + FD->getLocation(), + getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member + : diag::err_illegal_union_or_anon_struct_member) + << FD->getParent()->isUnion() << FD->getDeclName() + << llvm::to_underlying(member); DiagnoseNontrivial(RDecl, member); return !getLangOpts().CPlusPlus11; } @@ -19244,10 +19147,10 @@ static void ComputeSelectedDestructor(Sema &S, CXXRecordDecl *Record) { static bool AreSpecialMemberFunctionsSameKind(ASTContext &Context, CXXMethodDecl *M1, CXXMethodDecl *M2, - Sema::CXXSpecialMember CSM) { + CXXSpecialMemberKind CSM) { // We don't want to compare templates to non-templates: See // https://github.com/llvm/llvm-project/issues/59206 - if (CSM == Sema::CXXDefaultConstructor) + if (CSM == CXXSpecialMemberKind::DefaultConstructor) return bool(M1->getDescribedFunctionTemplate()) == bool(M2->getDescribedFunctionTemplate()); // FIXME: better resolve CWG @@ -19270,7 +19173,7 @@ static bool AreSpecialMemberFunctionsSameKind(ASTContext &Context, /// [CWG2595], if any, are satisfied is more constrained. static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record, ArrayRef Methods, - Sema::CXXSpecialMember CSM) { + CXXSpecialMemberKind CSM) { SmallVector SatisfactionStatus; for (CXXMethodDecl *Method : Methods) { @@ -19328,7 +19231,8 @@ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record, // DR1734 and DR1496. if (!AnotherMethodIsMoreConstrained) { Method->setIneligibleOrNotSelected(false); - Record->addedEligibleSpecialMemberFunction(Method, 1 << CSM); + Record->addedEligibleSpecialMemberFunction(Method, + 1 << llvm::to_underlying(CSM)); } } } @@ -19367,13 +19271,15 @@ static void ComputeSpecialMemberFunctionsEligiblity(Sema &S, } SetEligibleMethods(S, Record, DefaultConstructors, - Sema::CXXDefaultConstructor); - SetEligibleMethods(S, Record, CopyConstructors, Sema::CXXCopyConstructor); - SetEligibleMethods(S, Record, MoveConstructors, Sema::CXXMoveConstructor); + CXXSpecialMemberKind::DefaultConstructor); + SetEligibleMethods(S, Record, CopyConstructors, + CXXSpecialMemberKind::CopyConstructor); + SetEligibleMethods(S, Record, MoveConstructors, + CXXSpecialMemberKind::MoveConstructor); SetEligibleMethods(S, Record, CopyAssignmentOperators, - Sema::CXXCopyAssignment); + CXXSpecialMemberKind::CopyAssignment); SetEligibleMethods(S, Record, MoveAssignmentOperators, - Sema::CXXMoveAssignment); + CXXSpecialMemberKind::MoveAssignment); } void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, @@ -19742,7 +19648,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, if (CXXRecord) { auto *Dtor = CXXRecord->getDestructor(); if (Dtor && Dtor->isImplicit() && - ShouldDeleteSpecialMember(Dtor, CXXDestructor)) { + ShouldDeleteSpecialMember(Dtor, CXXSpecialMemberKind::Destructor)) { CXXRecord->setImplicitDestructorIsDeleted(); SetDeclDeleted(Dtor, CXXRecord->getLocation()); } @@ -20771,11 +20677,11 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(const FunctionDecl *FD, // when compiling for host, device and global functions are never emitted. // (Technically, we do emit a host-side stub for global functions, but this // doesn't count for our purposes here.) - Sema::CUDAFunctionTarget T = IdentifyCUDATarget(FD); - if (LangOpts.CUDAIsDevice && T == Sema::CFT_Host) + CUDAFunctionTarget T = CUDA().IdentifyTarget(FD); + if (LangOpts.CUDAIsDevice && T == CUDAFunctionTarget::Host) return FunctionEmissionStatus::CUDADiscarded; if (!LangOpts.CUDAIsDevice && - (T == Sema::CFT_Device || T == Sema::CFT_Global)) + (T == CUDAFunctionTarget::Device || T == CUDAFunctionTarget::Global)) return FunctionEmissionStatus::CUDADiscarded; if (IsEmittedForExternalSymbol()) @@ -20796,5 +20702,5 @@ bool Sema::shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee) { // for host, only HD functions actually called from the host get marked as // known-emitted. return LangOpts.CUDA && !LangOpts.CUDAIsDevice && - IdentifyCUDATarget(Callee) == CFT_Global; + CUDA().IdentifyTarget(Callee) == CUDAFunctionTarget::Global; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 8bce04640e748e8a419f6f76cfa38844568ea2c6..d26f130b5774cea8fc516820b3aabf4e5e0c152d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -39,9 +39,13 @@ #include "clang/Sema/ParsedAttr.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" +#include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Demangle/Demangle.h" #include "llvm/IR/Assumptions.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/Support/Error.h" @@ -1980,6 +1984,36 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) WeakRefAttr(S.Context, AL)); } +// Mark alias/ifunc target as used. Due to name mangling, we look up the +// demangled name ignoring parameters (not supported by microsoftDemangle +// https://github.com/llvm/llvm-project/issues/88825). This should handle the +// majority of use cases while leaving namespace scope names unmarked. +static void markUsedForAliasOrIfunc(Sema &S, Decl *D, const ParsedAttr &AL, + StringRef Str) { + std::unique_ptr Demangled; + if (S.getASTContext().getCXXABIKind() != TargetCXXABI::Microsoft) + Demangled.reset(llvm::itaniumDemangle(Str, /*ParseParams=*/false)); + std::unique_ptr MC(S.Context.createMangleContext()); + SmallString<256> Name; + + const DeclarationNameInfo Target( + &S.Context.Idents.get(Demangled ? Demangled.get() : Str), AL.getLoc()); + LookupResult LR(S, Target, Sema::LookupOrdinaryName); + if (S.LookupName(LR, S.TUScope)) { + for (NamedDecl *ND : LR) { + if (MC->shouldMangleDeclName(ND)) { + llvm::raw_svector_ostream Out(Name); + Name.clear(); + MC->mangleName(GlobalDecl(ND), Out); + } else { + Name = ND->getIdentifier()->getName(); + } + if (Name == Str) + ND->markUsed(S.Context); + } + } +} + static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) { StringRef Str; if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) @@ -1992,6 +2026,7 @@ static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } + markUsedForAliasOrIfunc(S, D, AL, Str); D->addAttr(::new (S.Context) IFuncAttr(S.Context, AL, Str)); } @@ -2026,17 +2061,7 @@ static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } } - // Mark target used to prevent unneeded-internal-declaration warnings. - if (!S.LangOpts.CPlusPlus) { - // FIXME: demangle Str for C++, as the attribute refers to the mangled - // linkage name, not the pre-mangled identifier. - const DeclarationNameInfo target(&S.Context.Idents.get(Str), AL.getLoc()); - LookupResult LR(S, target, Sema::LookupOrdinaryName); - if (S.LookupQualifiedName(LR, S.getCurLexicalContext())) - for (NamedDecl *ND : LR) - ND->markUsed(S.Context); - } - + markUsedForAliasOrIfunc(S, D, AL, Str); D->addAttr(::new (S.Context) AliasAttr(S.Context, AL, Str)); } @@ -5097,8 +5122,8 @@ static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } if (S.getLangOpts().CUDA && VD->hasLocalStorage() && - S.CUDADiagIfHostCode(AL.getLoc(), diag::err_cuda_host_shared) - << S.CurrentCUDATarget()) + S.CUDA().DiagIfHostCode(AL.getLoc(), diag::err_cuda_host_shared) + << llvm::to_underlying(S.CUDA().CurrentTarget())) return; D->addAttr(::new (S.Context) CUDASharedAttr(S.Context, AL)); } @@ -5187,8 +5212,9 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Diagnostic is emitted elsewhere: here we store the (valid) AL // in the Decl node for syntactic reasoning, e.g., pretty-printing. CallingConv CC; - if (S.CheckCallingConvAttr(AL, CC, /*FD*/ nullptr, - S.IdentifyCUDATarget(dyn_cast(D)))) + if (S.CheckCallingConvAttr( + AL, CC, /*FD*/ nullptr, + S.CUDA().IdentifyTarget(dyn_cast(D)))) return; if (!isa(D)) { @@ -5492,22 +5518,22 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, // on their host/device attributes. if (LangOpts.CUDA) { auto *Aux = Context.getAuxTargetInfo(); - assert(FD || CFT != CFT_InvalidTarget); - auto CudaTarget = FD ? IdentifyCUDATarget(FD) : CFT; + assert(FD || CFT != CUDAFunctionTarget::InvalidTarget); + auto CudaTarget = FD ? CUDA().IdentifyTarget(FD) : CFT; bool CheckHost = false, CheckDevice = false; switch (CudaTarget) { - case CFT_HostDevice: + case CUDAFunctionTarget::HostDevice: CheckHost = true; CheckDevice = true; break; - case CFT_Host: + case CUDAFunctionTarget::Host: CheckHost = true; break; - case CFT_Device: - case CFT_Global: + case CUDAFunctionTarget::Device: + case CUDAFunctionTarget::Global: CheckDevice = true; break; - case CFT_InvalidTarget: + case CUDAFunctionTarget::InvalidTarget: llvm_unreachable("unexpected cuda target"); } auto *HostTI = LangOpts.CUDAIsDevice ? Aux : &TI; @@ -7238,24 +7264,11 @@ static void handleHLSLNumThreadsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } - HLSLNumThreadsAttr *NewAttr = S.mergeHLSLNumThreadsAttr(D, AL, X, Y, Z); + HLSLNumThreadsAttr *NewAttr = S.HLSL().mergeNumThreadsAttr(D, AL, X, Y, Z); if (NewAttr) D->addAttr(NewAttr); } -HLSLNumThreadsAttr *Sema::mergeHLSLNumThreadsAttr(Decl *D, - const AttributeCommonInfo &AL, - int X, int Y, int Z) { - if (HLSLNumThreadsAttr *NT = D->getAttr()) { - if (NT->getX() != X || NT->getY() != Y || NT->getZ() != Z) { - Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL; - Diag(AL.getLoc(), diag::note_conflicting_attribute); - } - return nullptr; - } - return ::new (Context) HLSLNumThreadsAttr(Context, AL, X, Y, Z); -} - static bool isLegalTypeForHLSLSV_DispatchThreadID(QualType T) { if (!T->hasUnsignedIntegerRepresentation()) return false; @@ -7299,24 +7312,11 @@ static void handleHLSLShaderAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // FIXME: check function match the shader stage. - HLSLShaderAttr *NewAttr = S.mergeHLSLShaderAttr(D, AL, ShaderType); + HLSLShaderAttr *NewAttr = S.HLSL().mergeShaderAttr(D, AL, ShaderType); if (NewAttr) D->addAttr(NewAttr); } -HLSLShaderAttr * -Sema::mergeHLSLShaderAttr(Decl *D, const AttributeCommonInfo &AL, - HLSLShaderAttr::ShaderType ShaderType) { - if (HLSLShaderAttr *NT = D->getAttr()) { - if (NT->getType() != ShaderType) { - Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL; - Diag(AL.getLoc(), diag::note_conflicting_attribute); - } - return nullptr; - } - return HLSLShaderAttr::Create(Context, ShaderType, AL); -} - static void handleHLSLResourceBindingAttr(Sema &S, Decl *D, const ParsedAttr &AL) { StringRef Space = "space0"; @@ -7391,34 +7391,13 @@ static void handleHLSLResourceBindingAttr(Sema &S, Decl *D, static void handleHLSLParamModifierAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - HLSLParamModifierAttr *NewAttr = S.mergeHLSLParamModifierAttr( + HLSLParamModifierAttr *NewAttr = S.HLSL().mergeParamModifierAttr( D, AL, static_cast(AL.getSemanticSpelling())); if (NewAttr) D->addAttr(NewAttr); } -HLSLParamModifierAttr * -Sema::mergeHLSLParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, - HLSLParamModifierAttr::Spelling Spelling) { - // We can only merge an `in` attribute with an `out` attribute. All other - // combinations of duplicated attributes are ill-formed. - if (HLSLParamModifierAttr *PA = D->getAttr()) { - if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) || - (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) { - D->dropAttr(); - SourceRange AdjustedRange = {PA->getLocation(), AL.getRange().getEnd()}; - return HLSLParamModifierAttr::Create( - Context, /*MergedSpelling=*/true, AdjustedRange, - HLSLParamModifierAttr::Keyword_inout); - } - Diag(AL.getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL; - Diag(PA->getLocation(), diag::note_conflicting_attribute); - return nullptr; - } - return HLSLParamModifierAttr::Create(Context, AL); -} - static void handleMSInheritanceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!S.LangOpts.CPlusPlus) { S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 858951580ea45b9eddfae4427310ff8b1dcca90a..7669171fea56ff4bcd4673168e8ec65c2f230f80 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -42,10 +42,12 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -657,13 +659,13 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, // is ill-formed. This can only happen for constructors. if (isa(New) && New->getMinRequiredArguments() < Old->getMinRequiredArguments()) { - CXXSpecialMember NewSM = getSpecialMember(cast(New)), - OldSM = getSpecialMember(cast(Old)); + CXXSpecialMemberKind NewSM = getSpecialMember(cast(New)), + OldSM = getSpecialMember(cast(Old)); if (NewSM != OldSM) { ParmVarDecl *NewParam = New->getParamDecl(New->getMinRequiredArguments()); assert(NewParam->hasDefaultArg()); Diag(NewParam->getLocation(), diag::err_default_arg_makes_ctor_special) - << NewParam->getDefaultArgRange() << NewSM; + << NewParam->getDefaultArgRange() << llvm::to_underlying(NewSM); Diag(Old->getLocation(), diag::note_previous_declaration); } } @@ -6779,7 +6781,7 @@ void Sema::propagateDLLAttrToBaseClassTemplate( /// /// If the function is both a default constructor and a copy / move constructor /// (due to having a default argument for the first parameter), this picks -/// CXXDefaultConstructor. +/// CXXSpecialMemberKind::DefaultConstructor. /// /// FIXME: Check that case is properly handled by all callers. Sema::DefaultedFunctionKind @@ -6787,23 +6789,23 @@ Sema::getDefaultedFunctionKind(const FunctionDecl *FD) { if (auto *MD = dyn_cast(FD)) { if (const CXXConstructorDecl *Ctor = dyn_cast(FD)) { if (Ctor->isDefaultConstructor()) - return Sema::CXXDefaultConstructor; + return CXXSpecialMemberKind::DefaultConstructor; if (Ctor->isCopyConstructor()) - return Sema::CXXCopyConstructor; + return CXXSpecialMemberKind::CopyConstructor; if (Ctor->isMoveConstructor()) - return Sema::CXXMoveConstructor; + return CXXSpecialMemberKind::MoveConstructor; } if (MD->isCopyAssignmentOperator()) - return Sema::CXXCopyAssignment; + return CXXSpecialMemberKind::CopyAssignment; if (MD->isMoveAssignmentOperator()) - return Sema::CXXMoveAssignment; + return CXXSpecialMemberKind::MoveAssignment; if (isa(FD)) - return Sema::CXXDestructor; + return CXXSpecialMemberKind::Destructor; } switch (FD->getDeclName().getCXXOverloadedOperator()) { @@ -6843,26 +6845,26 @@ static void DefineDefaultedFunction(Sema &S, FunctionDecl *FD, return S.DefineDefaultedComparison(DefaultLoc, FD, DFK.asComparison()); switch (DFK.asSpecialMember()) { - case Sema::CXXDefaultConstructor: + case CXXSpecialMemberKind::DefaultConstructor: S.DefineImplicitDefaultConstructor(DefaultLoc, cast(FD)); break; - case Sema::CXXCopyConstructor: + case CXXSpecialMemberKind::CopyConstructor: S.DefineImplicitCopyConstructor(DefaultLoc, cast(FD)); break; - case Sema::CXXCopyAssignment: + case CXXSpecialMemberKind::CopyAssignment: S.DefineImplicitCopyAssignment(DefaultLoc, cast(FD)); break; - case Sema::CXXDestructor: + case CXXSpecialMemberKind::Destructor: S.DefineImplicitDestructor(DefaultLoc, cast(FD)); break; - case Sema::CXXMoveConstructor: + case CXXSpecialMemberKind::MoveConstructor: S.DefineImplicitMoveConstructor(DefaultLoc, cast(FD)); break; - case Sema::CXXMoveAssignment: + case CXXSpecialMemberKind::MoveAssignment: S.DefineImplicitMoveAssignment(DefaultLoc, cast(FD)); break; - case Sema::CXXInvalid: + case CXXSpecialMemberKind::Invalid: llvm_unreachable("Invalid special member."); } } @@ -7182,9 +7184,9 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { // For an explicitly defaulted or deleted special member, we defer // determining triviality until the class is complete. That time is now! - CXXSpecialMember CSM = getSpecialMember(M); + CXXSpecialMemberKind CSM = getSpecialMember(M); if (!M->isImplicit() && !M->isUserProvided()) { - if (CSM != CXXInvalid) { + if (CSM != CXXSpecialMemberKind::Invalid) { M->setTrivial(SpecialMemberIsTrivial(M, CSM)); // Inform the class that we've finished declaring this member. Record->finishedDefaultedOrDeletedMember(M); @@ -7197,8 +7199,10 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { // Set triviality for the purpose of calls if this is a user-provided // copy/move constructor or destructor. - if ((CSM == CXXCopyConstructor || CSM == CXXMoveConstructor || - CSM == CXXDestructor) && M->isUserProvided()) { + if ((CSM == CXXSpecialMemberKind::CopyConstructor || + CSM == CXXSpecialMemberKind::MoveConstructor || + CSM == CXXSpecialMemberKind::Destructor) && + M->isUserProvided()) { M->setTrivialForCall(HasTrivialABI); Record->setTrivialForCallFlags(M); } @@ -7207,8 +7211,9 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { M->hasAttr()) { if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) && M->isTrivial() && - (CSM == CXXDefaultConstructor || CSM == CXXCopyConstructor || - CSM == CXXDestructor)) + (CSM == CXXSpecialMemberKind::DefaultConstructor || + CSM == CXXSpecialMemberKind::CopyConstructor || + CSM == CXXSpecialMemberKind::Destructor)) M->dropAttr(); if (M->hasAttr()) { @@ -7220,8 +7225,8 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { // Define defaulted constexpr virtual functions that override a base class // function right away. // FIXME: We can defer doing this until the vtable is marked as used. - if (CSM != CXXInvalid && !M->isDeleted() && M->isDefaulted() && - M->isConstexpr() && M->size_overridden_methods()) + if (CSM != CXXSpecialMemberKind::Invalid && !M->isDeleted() && + M->isDefaulted() && M->isConstexpr() && M->size_overridden_methods()) DefineDefaultedFunction(*this, M, M->getLocation()); if (!Incomplete) @@ -7343,15 +7348,18 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { /// \param ConstRHS True if this is a copy operation with a const object /// on its RHS, that is, if the argument to the outer special member /// function is 'const' and this is not a field marked 'mutable'. -static Sema::SpecialMemberOverloadResult lookupCallFromSpecialMember( - Sema &S, CXXRecordDecl *Class, Sema::CXXSpecialMember CSM, - unsigned FieldQuals, bool ConstRHS) { +static Sema::SpecialMemberOverloadResult +lookupCallFromSpecialMember(Sema &S, CXXRecordDecl *Class, + CXXSpecialMemberKind CSM, unsigned FieldQuals, + bool ConstRHS) { unsigned LHSQuals = 0; - if (CSM == Sema::CXXCopyAssignment || CSM == Sema::CXXMoveAssignment) + if (CSM == CXXSpecialMemberKind::CopyAssignment || + CSM == CXXSpecialMemberKind::MoveAssignment) LHSQuals = FieldQuals; unsigned RHSQuals = FieldQuals; - if (CSM == Sema::CXXDefaultConstructor || CSM == Sema::CXXDestructor) + if (CSM == CXXSpecialMemberKind::DefaultConstructor || + CSM == CXXSpecialMemberKind::Destructor) RHSQuals = 0; else if (ConstRHS) RHSQuals |= Qualifiers::Const; @@ -7447,12 +7455,10 @@ public: /// Is the special member function which would be selected to perform the /// specified operation on the specified class type a constexpr constructor? -static bool -specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, - Sema::CXXSpecialMember CSM, unsigned Quals, - bool ConstRHS, - CXXConstructorDecl *InheritedCtor = nullptr, - Sema::InheritedConstructorInfo *Inherited = nullptr) { +static bool specialMemberIsConstexpr( + Sema &S, CXXRecordDecl *ClassDecl, CXXSpecialMemberKind CSM, unsigned Quals, + bool ConstRHS, CXXConstructorDecl *InheritedCtor = nullptr, + Sema::InheritedConstructorInfo *Inherited = nullptr) { // Suppress duplicate constraint checking here, in case a constraint check // caused us to decide to do this. Any truely recursive checks will get // caught during these checks anyway. @@ -7461,16 +7467,16 @@ specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, // If we're inheriting a constructor, see if we need to call it for this base // class. if (InheritedCtor) { - assert(CSM == Sema::CXXDefaultConstructor); + assert(CSM == CXXSpecialMemberKind::DefaultConstructor); auto BaseCtor = Inherited->findConstructorForBase(ClassDecl, InheritedCtor).first; if (BaseCtor) return BaseCtor->isConstexpr(); } - if (CSM == Sema::CXXDefaultConstructor) + if (CSM == CXXSpecialMemberKind::DefaultConstructor) return ClassDecl->hasConstexprDefaultConstructor(); - if (CSM == Sema::CXXDestructor) + if (CSM == CXXSpecialMemberKind::Destructor) return ClassDecl->hasConstexprDestructor(); Sema::SpecialMemberOverloadResult SMOR = @@ -7485,8 +7491,8 @@ specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, /// Determine whether the specified special member function would be constexpr /// if it were implicitly defined. static bool defaultedSpecialMemberIsConstexpr( - Sema &S, CXXRecordDecl *ClassDecl, Sema::CXXSpecialMember CSM, - bool ConstArg, CXXConstructorDecl *InheritedCtor = nullptr, + Sema &S, CXXRecordDecl *ClassDecl, CXXSpecialMemberKind CSM, bool ConstArg, + CXXConstructorDecl *InheritedCtor = nullptr, Sema::InheritedConstructorInfo *Inherited = nullptr) { if (!S.getLangOpts().CPlusPlus11) return false; @@ -7495,7 +7501,7 @@ static bool defaultedSpecialMemberIsConstexpr( // In the definition of a constexpr constructor [...] bool Ctor = true; switch (CSM) { - case Sema::CXXDefaultConstructor: + case CXXSpecialMemberKind::DefaultConstructor: if (Inherited) break; // Since default constructor lookup is essentially trivial (and cannot @@ -7506,23 +7512,23 @@ static bool defaultedSpecialMemberIsConstexpr( // constructor is constexpr to determine whether the type is a literal type. return ClassDecl->defaultedDefaultConstructorIsConstexpr(); - case Sema::CXXCopyConstructor: - case Sema::CXXMoveConstructor: + case CXXSpecialMemberKind::CopyConstructor: + case CXXSpecialMemberKind::MoveConstructor: // For copy or move constructors, we need to perform overload resolution. break; - case Sema::CXXCopyAssignment: - case Sema::CXXMoveAssignment: + case CXXSpecialMemberKind::CopyAssignment: + case CXXSpecialMemberKind::MoveAssignment: if (!S.getLangOpts().CPlusPlus14) return false; // In C++1y, we need to perform overload resolution. Ctor = false; break; - case Sema::CXXDestructor: + case CXXSpecialMemberKind::Destructor: return ClassDecl->defaultedDestructorIsConstexpr(); - case Sema::CXXInvalid: + case CXXSpecialMemberKind::Invalid: return false; } @@ -7534,7 +7540,7 @@ static bool defaultedSpecialMemberIsConstexpr( // will be initialized (if the constructor isn't deleted), we just don't know // which one. if (Ctor && ClassDecl->isUnion()) - return CSM == Sema::CXXDefaultConstructor + return CSM == CXXSpecialMemberKind::DefaultConstructor ? ClassDecl->hasInClassInitializer() || !ClassDecl->hasVariantMembers() : true; @@ -7575,7 +7581,8 @@ static bool defaultedSpecialMemberIsConstexpr( for (const auto *F : ClassDecl->fields()) { if (F->isInvalidDecl()) continue; - if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer()) + if (CSM == CXXSpecialMemberKind::DefaultConstructor && + F->hasInClassInitializer()) continue; QualType BaseType = S.Context.getBaseElementType(F->getType()); if (const RecordType *RecordTy = BaseType->getAs()) { @@ -7584,7 +7591,7 @@ static bool defaultedSpecialMemberIsConstexpr( BaseType.getCVRQualifiers(), ConstArg && !F->isMutable())) return false; - } else if (CSM == Sema::CXXDefaultConstructor) { + } else if (CSM == CXXSpecialMemberKind::DefaultConstructor) { return false; } } @@ -7615,9 +7622,10 @@ struct ComputingExceptionSpec { } static Sema::ImplicitExceptionSpecification -ComputeDefaultedSpecialMemberExceptionSpec( - Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, - Sema::InheritedConstructorInfo *ICI); +ComputeDefaultedSpecialMemberExceptionSpec(Sema &S, SourceLocation Loc, + CXXMethodDecl *MD, + CXXSpecialMemberKind CSM, + Sema::InheritedConstructorInfo *ICI); static Sema::ImplicitExceptionSpecification ComputeDefaultedComparisonExceptionSpec(Sema &S, SourceLocation Loc, @@ -7641,7 +7649,7 @@ computeImplicitExceptionSpec(Sema &S, SourceLocation Loc, FunctionDecl *FD) { Sema::InheritedConstructorInfo ICI( S, Loc, CD->getInheritedConstructor().getShadowDecl()); return ComputeDefaultedSpecialMemberExceptionSpec( - S, Loc, CD, Sema::CXXDefaultConstructor, &ICI); + S, Loc, CD, CXXSpecialMemberKind::DefaultConstructor, &ICI); } static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S, @@ -7693,11 +7701,11 @@ void Sema::CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *FD) { } bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, - CXXSpecialMember CSM, + CXXSpecialMemberKind CSM, SourceLocation DefaultLoc) { CXXRecordDecl *RD = MD->getParent(); - assert(MD->isExplicitlyDefaulted() && CSM != CXXInvalid && + assert(MD->isExplicitlyDefaulted() && CSM != CXXSpecialMemberKind::Invalid && "not an explicitly-defaulted special member"); // Defer all checking for special members of a dependent type. @@ -7723,21 +7731,22 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, bool DeleteOnTypeMismatch = getLangOpts().CPlusPlus20 && First; bool ShouldDeleteForTypeMismatch = false; unsigned ExpectedParams = 1; - if (CSM == CXXDefaultConstructor || CSM == CXXDestructor) + if (CSM == CXXSpecialMemberKind::DefaultConstructor || + CSM == CXXSpecialMemberKind::Destructor) ExpectedParams = 0; if (MD->getNumExplicitParams() != ExpectedParams) { // This checks for default arguments: a copy or move constructor with a // default argument is classified as a default constructor, and assignment // operations and destructors can't have default arguments. Diag(MD->getLocation(), diag::err_defaulted_special_member_params) - << CSM << MD->getSourceRange(); + << llvm::to_underlying(CSM) << MD->getSourceRange(); HadError = true; } else if (MD->isVariadic()) { if (DeleteOnTypeMismatch) ShouldDeleteForTypeMismatch = true; else { Diag(MD->getLocation(), diag::err_defaulted_special_member_variadic) - << CSM << MD->getSourceRange(); + << llvm::to_underlying(CSM) << MD->getSourceRange(); HadError = true; } } @@ -7745,13 +7754,14 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, const FunctionProtoType *Type = MD->getType()->castAs(); bool CanHaveConstParam = false; - if (CSM == CXXCopyConstructor) + if (CSM == CXXSpecialMemberKind::CopyConstructor) CanHaveConstParam = RD->implicitCopyConstructorHasConstParam(); - else if (CSM == CXXCopyAssignment) + else if (CSM == CXXSpecialMemberKind::CopyAssignment) CanHaveConstParam = RD->implicitCopyAssignmentHasConstParam(); QualType ReturnType = Context.VoidTy; - if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) { + if (CSM == CXXSpecialMemberKind::CopyAssignment || + CSM == CXXSpecialMemberKind::MoveAssignment) { // Check for return type matching. ReturnType = Type->getReturnType(); QualType ThisType = MD->getFunctionObjectParameterType(); @@ -7765,7 +7775,8 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, if (!Context.hasSameType(ReturnType, ExpectedReturnType)) { Diag(MD->getLocation(), diag::err_defaulted_special_member_return_type) - << (CSM == CXXMoveAssignment) << ExpectedReturnType; + << (CSM == CXXSpecialMemberKind::MoveAssignment) + << ExpectedReturnType; HadError = true; } @@ -7775,7 +7786,8 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, ShouldDeleteForTypeMismatch = true; else { Diag(MD->getLocation(), diag::err_defaulted_special_member_quals) - << (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus14; + << (CSM == CXXSpecialMemberKind::MoveAssignment) + << getLangOpts().CPlusPlus14; HadError = true; } } @@ -7793,7 +7805,8 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, else { Diag(MD->getLocation(), diag::err_defaulted_special_member_explicit_object_mismatch) - << (CSM == CXXMoveAssignment) << RD << MD->getSourceRange(); + << (CSM == CXXSpecialMemberKind::MoveAssignment) << RD + << MD->getSourceRange(); HadError = true; } } @@ -7815,7 +7828,8 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, ShouldDeleteForTypeMismatch = true; else { Diag(MD->getLocation(), - diag::err_defaulted_special_member_volatile_param) << CSM; + diag::err_defaulted_special_member_volatile_param) + << llvm::to_underlying(CSM); HadError = true; } } @@ -7823,23 +7837,25 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, if (HasConstParam && !CanHaveConstParam) { if (DeleteOnTypeMismatch) ShouldDeleteForTypeMismatch = true; - else if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment) { + else if (CSM == CXXSpecialMemberKind::CopyConstructor || + CSM == CXXSpecialMemberKind::CopyAssignment) { Diag(MD->getLocation(), diag::err_defaulted_special_member_copy_const_param) - << (CSM == CXXCopyAssignment); + << (CSM == CXXSpecialMemberKind::CopyAssignment); // FIXME: Explain why this special member can't be const. HadError = true; } else { Diag(MD->getLocation(), diag::err_defaulted_special_member_move_const_param) - << (CSM == CXXMoveAssignment); + << (CSM == CXXSpecialMemberKind::MoveAssignment); HadError = true; } } } else if (ExpectedParams) { // A copy assignment operator can take its argument by value, but a // defaulted one cannot. - assert(CSM == CXXCopyAssignment && "unexpected non-ref argument"); + assert(CSM == CXXSpecialMemberKind::CopyAssignment && + "unexpected non-ref argument"); Diag(MD->getLocation(), diag::err_defaulted_copy_assign_not_ref); HadError = true; } @@ -7874,12 +7890,12 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, if (!MD->isConsteval() && RD->getNumVBases()) { Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr_with_vb) - << CSM; + << llvm::to_underlying(CSM); for (const auto &I : RD->vbases()) Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here); } else { Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr) - << CSM << MD->isConsteval(); + << llvm::to_underlying(CSM) << MD->isConsteval(); } HadError = true; // FIXME: Explain why the special member can't be constexpr. @@ -7912,9 +7928,11 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, if (First) { SetDeclDeleted(MD, MD->getLocation()); if (!inTemplateInstantiation() && !HadError) { - Diag(MD->getLocation(), diag::warn_defaulted_method_deleted) << CSM; + Diag(MD->getLocation(), diag::warn_defaulted_method_deleted) + << llvm::to_underlying(CSM); if (ShouldDeleteForTypeMismatch) { - Diag(MD->getLocation(), diag::note_deleted_type_mismatch) << CSM; + Diag(MD->getLocation(), diag::note_deleted_type_mismatch) + << llvm::to_underlying(CSM); } else if (ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/ true) && DefaultLoc.isValid()) { @@ -7924,13 +7942,15 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, } if (ShouldDeleteForTypeMismatch && !HadError) { Diag(MD->getLocation(), - diag::warn_cxx17_compat_defaulted_method_type_mismatch) << CSM; + diag::warn_cxx17_compat_defaulted_method_type_mismatch) + << llvm::to_underlying(CSM); } } else { // C++11 [dcl.fct.def.default]p4: // [For a] user-provided explicitly-defaulted function [...] if such a // function is implicitly defined as deleted, the program is ill-formed. - Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM; + Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) + << llvm::to_underlying(CSM); assert(!ShouldDeleteForTypeMismatch && "deleted non-first decl"); ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true); HadError = true; @@ -7962,7 +7982,7 @@ public: DefaultedComparisonVisitor(Sema &S, CXXRecordDecl *RD, FunctionDecl *FD, DefaultedComparisonKind DCK) : S(S), RD(RD), FD(FD), DCK(DCK) { - if (auto *Info = FD->getDefaultedFunctionInfo()) { + if (auto *Info = FD->getDefalutedOrDeletedInfo()) { // FIXME: Change CreateOverloadedBinOp to take an ArrayRef instead of an // UnresolvedSet to avoid this copy. Fns.assign(Info->getUnqualifiedLookups().begin(), @@ -8830,8 +8850,9 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, UnresolvedSet<32> Operators; lookupOperatorsForDefaultedComparison(*this, S, Operators, FD->getOverloadedOperator()); - FD->setDefaultedFunctionInfo(FunctionDecl::DefaultedFunctionInfo::Create( - Context, Operators.pairs())); + FD->setDefaultedOrDeletedInfo( + FunctionDecl::DefaultedOrDeletedFunctionInfo::Create( + Context, Operators.pairs())); } // C++2a [class.compare.default]p1: @@ -9271,28 +9292,28 @@ template struct SpecialMemberVisitor { Sema &S; CXXMethodDecl *MD; - Sema::CXXSpecialMember CSM; + CXXSpecialMemberKind CSM; Sema::InheritedConstructorInfo *ICI; // Properties of the special member, computed for convenience. bool IsConstructor = false, IsAssignment = false, ConstArg = false; - SpecialMemberVisitor(Sema &S, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, + SpecialMemberVisitor(Sema &S, CXXMethodDecl *MD, CXXSpecialMemberKind CSM, Sema::InheritedConstructorInfo *ICI) : S(S), MD(MD), CSM(CSM), ICI(ICI) { switch (CSM) { - case Sema::CXXDefaultConstructor: - case Sema::CXXCopyConstructor: - case Sema::CXXMoveConstructor: + case CXXSpecialMemberKind::DefaultConstructor: + case CXXSpecialMemberKind::CopyConstructor: + case CXXSpecialMemberKind::MoveConstructor: IsConstructor = true; break; - case Sema::CXXCopyAssignment: - case Sema::CXXMoveAssignment: + case CXXSpecialMemberKind::CopyAssignment: + case CXXSpecialMemberKind::MoveAssignment: IsAssignment = true; break; - case Sema::CXXDestructor: + case CXXSpecialMemberKind::Destructor: break; - case Sema::CXXInvalid: + case CXXSpecialMemberKind::Invalid: llvm_unreachable("invalid special member kind"); } @@ -9307,7 +9328,8 @@ struct SpecialMemberVisitor { /// Is this a "move" special member? bool isMove() const { - return CSM == Sema::CXXMoveConstructor || CSM == Sema::CXXMoveAssignment; + return CSM == CXXSpecialMemberKind::MoveConstructor || + CSM == CXXSpecialMemberKind::MoveAssignment; } /// Look up the corresponding special member in the given class. @@ -9322,7 +9344,7 @@ struct SpecialMemberVisitor { Sema::SpecialMemberOverloadResult lookupInheritedCtor(CXXRecordDecl *Class) { if (!ICI) return {}; - assert(CSM == Sema::CXXDefaultConstructor); + assert(CSM == CXXSpecialMemberKind::DefaultConstructor); auto *BaseCtor = cast(MD)->getInheritedConstructor().getConstructor(); if (auto *MD = ICI->findConstructorForBase(Class, BaseCtor).first) @@ -9392,15 +9414,15 @@ struct SpecialMemberDeletionInfo bool AllFieldsAreConst; SpecialMemberDeletionInfo(Sema &S, CXXMethodDecl *MD, - Sema::CXXSpecialMember CSM, + CXXSpecialMemberKind CSM, Sema::InheritedConstructorInfo *ICI, bool Diagnose) : SpecialMemberVisitor(S, MD, CSM, ICI), Diagnose(Diagnose), Loc(MD->getLocation()), AllFieldsAreConst(true) {} bool inUnion() const { return MD->getParent()->isUnion(); } - Sema::CXXSpecialMember getEffectiveCSM() { - return ICI ? Sema::CXXInvalid : CSM; + CXXSpecialMemberKind getEffectiveCSM() { + return ICI ? CXXSpecialMemberKind::Invalid : CSM; } bool shouldDeleteForVariantObjCPtrMember(FieldDecl *FD, QualType FieldType); @@ -9466,7 +9488,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( // must be accessible and non-deleted, but need not be trivial. Such a // destructor is never actually called, but is semantically checked as // if it were. - if (CSM == Sema::CXXDefaultConstructor) { + if (CSM == CXXSpecialMemberKind::DefaultConstructor) { // [class.default.ctor]p2: // A defaulted default constructor for class X is defined as deleted if // - X is a union that has a variant member with a non-trivial default @@ -9487,15 +9509,16 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( if (Field) { S.Diag(Field->getLocation(), diag::note_deleted_special_member_class_subobject) - << getEffectiveCSM() << MD->getParent() << /*IsField*/true - << Field << DiagKind << IsDtorCallInCtor << /*IsObjCPtr*/false; + << llvm::to_underlying(getEffectiveCSM()) << MD->getParent() + << /*IsField*/ true << Field << DiagKind << IsDtorCallInCtor + << /*IsObjCPtr*/ false; } else { CXXBaseSpecifier *Base = Subobj.get(); S.Diag(Base->getBeginLoc(), diag::note_deleted_special_member_class_subobject) - << getEffectiveCSM() << MD->getParent() << /*IsField*/ false - << Base->getType() << DiagKind << IsDtorCallInCtor - << /*IsObjCPtr*/false; + << llvm::to_underlying(getEffectiveCSM()) << MD->getParent() + << /*IsField*/ false << Base->getType() << DiagKind + << IsDtorCallInCtor << /*IsObjCPtr*/ false; } if (DiagKind == 1) @@ -9527,8 +9550,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject( // C++11 [class.dtor]p5: // -- any direct or virtual base class [...] has a type with a destructor // that is deleted or inaccessible - if (!(CSM == Sema::CXXDefaultConstructor && - Field && Field->hasInClassInitializer()) && + if (!(CSM == CXXSpecialMemberKind::DefaultConstructor && Field && + Field->hasInClassInitializer()) && shouldDeleteForSubobjectCall(Subobj, lookupIn(Class, Quals, IsMutable), false)) return true; @@ -9538,8 +9561,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject( // type with a destructor that is deleted or inaccessible if (IsConstructor) { Sema::SpecialMemberOverloadResult SMOR = - S.LookupSpecialMember(Class, Sema::CXXDestructor, - false, false, false, false, false); + S.LookupSpecialMember(Class, CXXSpecialMemberKind::Destructor, false, + false, false, false, false); if (shouldDeleteForSubobjectCall(Subobj, SMOR, true)) return true; } @@ -9557,15 +9580,16 @@ bool SpecialMemberDeletionInfo::shouldDeleteForVariantObjCPtrMember( // Don't make the defaulted default constructor defined as deleted if the // member has an in-class initializer. - if (CSM == Sema::CXXDefaultConstructor && FD->hasInClassInitializer()) + if (CSM == CXXSpecialMemberKind::DefaultConstructor && + FD->hasInClassInitializer()) return false; if (Diagnose) { auto *ParentClass = cast(FD->getParent()); - S.Diag(FD->getLocation(), - diag::note_deleted_special_member_class_subobject) - << getEffectiveCSM() << ParentClass << /*IsField*/true - << FD << 4 << /*IsDtorCallInCtor*/false << /*IsObjCPtr*/true; + S.Diag(FD->getLocation(), diag::note_deleted_special_member_class_subobject) + << llvm::to_underlying(getEffectiveCSM()) << ParentClass + << /*IsField*/ true << FD << 4 << /*IsDtorCallInCtor*/ false + << /*IsObjCPtr*/ true; } return true; @@ -9590,9 +9614,9 @@ bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) { if (BaseCtor->isDeleted() && Diagnose) { S.Diag(Base->getBeginLoc(), diag::note_deleted_special_member_class_subobject) - << getEffectiveCSM() << MD->getParent() << /*IsField*/ false - << Base->getType() << /*Deleted*/ 1 << /*IsDtorCallInCtor*/ false - << /*IsObjCPtr*/false; + << llvm::to_underlying(getEffectiveCSM()) << MD->getParent() + << /*IsField*/ false << Base->getType() << /*Deleted*/ 1 + << /*IsDtorCallInCtor*/ false << /*IsObjCPtr*/ false; S.NoteDeletedFunction(BaseCtor); } return BaseCtor->isDeleted(); @@ -9609,7 +9633,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { if (inUnion() && shouldDeleteForVariantObjCPtrMember(FD, FieldType)) return true; - if (CSM == Sema::CXXDefaultConstructor) { + if (CSM == CXXSpecialMemberKind::DefaultConstructor) { // For a default constructor, all references must be initialized in-class // and, if a union, it must have a non-const member. if (FieldType->isReferenceType() && !FD->hasInClassInitializer()) { @@ -9632,7 +9656,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { if (inUnion() && !FieldType.isConstQualified()) AllFieldsAreConst = false; - } else if (CSM == Sema::CXXCopyConstructor) { + } else if (CSM == CXXSpecialMemberKind::CopyConstructor) { // For a copy constructor, data members must not be of rvalue reference // type. if (FieldType->isRValueReferenceType()) { @@ -9683,8 +9707,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { } // At least one member in each anonymous union must be non-const - if (CSM == Sema::CXXDefaultConstructor && AllVariantFieldsAreConst && - !FieldRecord->field_empty()) { + if (CSM == CXXSpecialMemberKind::DefaultConstructor && + AllVariantFieldsAreConst && !FieldRecord->field_empty()) { if (Diagnose) S.Diag(FieldRecord->getLocation(), diag::note_deleted_default_ctor_all_const) @@ -9712,7 +9736,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() { // This is a silly definition, because it gives an empty union a deleted // default constructor. Don't do that. - if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst) { + if (CSM == CXXSpecialMemberKind::DefaultConstructor && inUnion() && + AllFieldsAreConst) { bool AnyFields = false; for (auto *F : MD->getParent()->fields()) if ((AnyFields = !F->isUnnamedBitfield())) @@ -9731,7 +9756,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() { /// Determine whether a defaulted special member function should be defined as /// deleted, as specified in C++11 [class.ctor]p5, C++11 [class.copy]p11, /// C++11 [class.copy]p23, and C++11 [class.dtor]p5. -bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, +bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, + CXXSpecialMemberKind CSM, InheritedConstructorInfo *ICI, bool Diagnose) { if (MD->isInvalidDecl()) @@ -9748,7 +9774,8 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, // assignment operator. // C++2a adds back these operators if the lambda has no lambda-capture. if (RD->isLambda() && !RD->lambdaIsDefaultConstructibleAndAssignable() && - (CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment)) { + (CSM == CXXSpecialMemberKind::DefaultConstructor || + CSM == CXXSpecialMemberKind::CopyAssignment)) { if (Diagnose) Diag(RD->getLocation(), diag::note_lambda_decl); return true; @@ -9757,16 +9784,16 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, // For an anonymous struct or union, the copy and assignment special members // will never be used, so skip the check. For an anonymous union declared at // namespace scope, the constructor and destructor are used. - if (CSM != CXXDefaultConstructor && CSM != CXXDestructor && - RD->isAnonymousStructOrUnion()) + if (CSM != CXXSpecialMemberKind::DefaultConstructor && + CSM != CXXSpecialMemberKind::Destructor && RD->isAnonymousStructOrUnion()) return false; // C++11 [class.copy]p7, p18: // If the class definition declares a move constructor or move assignment // operator, an implicitly declared copy constructor or copy assignment // operator is defined as deleted. - if (MD->isImplicit() && - (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)) { + if (MD->isImplicit() && (CSM == CXXSpecialMemberKind::CopyConstructor || + CSM == CXXSpecialMemberKind::CopyAssignment)) { CXXMethodDecl *UserDeclaredMove = nullptr; // In Microsoft mode up to MSVC 2013, a user-declared move only causes the @@ -9777,7 +9804,8 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015); if (RD->hasUserDeclaredMoveConstructor() && - (!DeletesOnlyMatchingCopy || CSM == CXXCopyConstructor)) { + (!DeletesOnlyMatchingCopy || + CSM == CXXSpecialMemberKind::CopyConstructor)) { if (!Diagnose) return true; // Find any user-declared move constructor. @@ -9789,7 +9817,8 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, } assert(UserDeclaredMove); } else if (RD->hasUserDeclaredMoveAssignment() && - (!DeletesOnlyMatchingCopy || CSM == CXXCopyAssignment)) { + (!DeletesOnlyMatchingCopy || + CSM == CXXSpecialMemberKind::CopyAssignment)) { if (!Diagnose) return true; // Find any user-declared move assignment operator. @@ -9805,8 +9834,8 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, if (UserDeclaredMove) { Diag(UserDeclaredMove->getLocation(), diag::note_deleted_copy_user_declared_move) - << (CSM == CXXCopyAssignment) << RD - << UserDeclaredMove->isMoveAssignmentOperator(); + << (CSM == CXXSpecialMemberKind::CopyAssignment) << RD + << UserDeclaredMove->isMoveAssignmentOperator(); return true; } } @@ -9817,7 +9846,7 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, // C++11 [class.dtor]p5: // -- for a virtual destructor, lookup of the non-array deallocation function // results in an ambiguity or in a function that is deleted or inaccessible - if (CSM == CXXDestructor && MD->isVirtual()) { + if (CSM == CXXSpecialMemberKind::Destructor && MD->isVirtual()) { FunctionDecl *OperatorDelete = nullptr; DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Delete); @@ -9849,15 +9878,15 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, // failed. // For inherited constructors (non-null ICI), CSM may be passed so that MD // is treated as certain special member, which may not reflect what special - // member MD really is. However inferCUDATargetForImplicitSpecialMember + // member MD really is. However inferTargetForImplicitSpecialMember // expects CSM to match MD, therefore recalculate CSM. assert(ICI || CSM == getSpecialMember(MD)); auto RealCSM = CSM; if (ICI) RealCSM = getSpecialMember(MD); - return inferCUDATargetForImplicitSpecialMember(RD, RealCSM, MD, - SMI.ConstArg, Diagnose); + return CUDA().inferTargetForImplicitSpecialMember(RD, RealCSM, MD, + SMI.ConstArg, Diagnose); } return false; @@ -9891,7 +9920,7 @@ void Sema::DiagnoseDeletedDefaultedFunction(FunctionDecl *FD) { /// If \p ForCall is true, look at CXXRecord::HasTrivialSpecialMembersForCall to /// determine whether the special member is trivial. static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, - Sema::CXXSpecialMember CSM, unsigned Quals, + CXXSpecialMemberKind CSM, unsigned Quals, bool ConstRHS, Sema::TrivialABIHandling TAH, CXXMethodDecl **Selected) { @@ -9899,10 +9928,10 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, *Selected = nullptr; switch (CSM) { - case Sema::CXXInvalid: + case CXXSpecialMemberKind::Invalid: llvm_unreachable("not a special member"); - case Sema::CXXDefaultConstructor: + case CXXSpecialMemberKind::DefaultConstructor: // C++11 [class.ctor]p5: // A default constructor is trivial if: // - all the [direct subobjects] have trivial default constructors @@ -9931,7 +9960,7 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, return false; - case Sema::CXXDestructor: + case CXXSpecialMemberKind::Destructor: // C++11 [class.dtor]p5: // A destructor is trivial if: // - all the direct [subobjects] have trivial destructors @@ -9948,7 +9977,7 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, return false; - case Sema::CXXCopyConstructor: + case CXXSpecialMemberKind::CopyConstructor: // C++11 [class.copy]p12: // A copy constructor is trivial if: // - the constructor selected to copy each direct [subobject] is trivial @@ -9969,7 +9998,7 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, // struct B { mutable A a; }; goto NeedOverloadResolution; - case Sema::CXXCopyAssignment: + case CXXSpecialMemberKind::CopyAssignment: // C++11 [class.copy]p25: // A copy assignment operator is trivial if: // - the assignment operator selected to copy each direct [subobject] is @@ -9984,8 +10013,8 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, // treat that as a language defect. goto NeedOverloadResolution; - case Sema::CXXMoveConstructor: - case Sema::CXXMoveAssignment: + case CXXSpecialMemberKind::MoveConstructor: + case CXXSpecialMemberKind::MoveAssignment: NeedOverloadResolution: Sema::SpecialMemberOverloadResult SMOR = lookupCallFromSpecialMember(S, RD, CSM, Quals, ConstRHS); @@ -10009,7 +10038,8 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, *Selected = SMOR.getMethod(); if (TAH == Sema::TAH_ConsiderTrivialABI && - (CSM == Sema::CXXCopyConstructor || CSM == Sema::CXXMoveConstructor)) + (CSM == CXXSpecialMemberKind::CopyConstructor || + CSM == CXXSpecialMemberKind::MoveConstructor)) return SMOR.getMethod()->isTrivialForCall(); return SMOR.getMethod()->isTrivial(); } @@ -10047,9 +10077,10 @@ enum TrivialSubobjectKind { /// Check whether the special member selected for a given type would be trivial. static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc, QualType SubType, bool ConstRHS, - Sema::CXXSpecialMember CSM, + CXXSpecialMemberKind CSM, TrivialSubobjectKind Kind, - Sema::TrivialABIHandling TAH, bool Diagnose) { + Sema::TrivialABIHandling TAH, + bool Diagnose) { CXXRecordDecl *SubRD = SubType->getAsCXXRecordDecl(); if (!SubRD) return true; @@ -10063,27 +10094,28 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc, if (ConstRHS) SubType.addConst(); - if (!Selected && CSM == Sema::CXXDefaultConstructor) { + if (!Selected && CSM == CXXSpecialMemberKind::DefaultConstructor) { S.Diag(SubobjLoc, diag::note_nontrivial_no_def_ctor) << Kind << SubType.getUnqualifiedType(); if (CXXConstructorDecl *CD = findUserDeclaredCtor(SubRD)) S.Diag(CD->getLocation(), diag::note_user_declared_ctor); } else if (!Selected) S.Diag(SubobjLoc, diag::note_nontrivial_no_copy) - << Kind << SubType.getUnqualifiedType() << CSM << SubType; + << Kind << SubType.getUnqualifiedType() << llvm::to_underlying(CSM) + << SubType; else if (Selected->isUserProvided()) { if (Kind == TSK_CompleteObject) S.Diag(Selected->getLocation(), diag::note_nontrivial_user_provided) - << Kind << SubType.getUnqualifiedType() << CSM; + << Kind << SubType.getUnqualifiedType() << llvm::to_underlying(CSM); else { S.Diag(SubobjLoc, diag::note_nontrivial_user_provided) - << Kind << SubType.getUnqualifiedType() << CSM; + << Kind << SubType.getUnqualifiedType() << llvm::to_underlying(CSM); S.Diag(Selected->getLocation(), diag::note_declared_at); } } else { if (Kind != TSK_CompleteObject) S.Diag(SubobjLoc, diag::note_nontrivial_subobject) - << Kind << SubType.getUnqualifiedType() << CSM; + << Kind << SubType.getUnqualifiedType() << llvm::to_underlying(CSM); // Explain why the defaulted or deleted special member isn't trivial. S.SpecialMemberIsTrivial(Selected, CSM, Sema::TAH_IgnoreTrivialABI, @@ -10097,8 +10129,7 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc, /// Check whether the members of a class type allow a special member to be /// trivial. static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, - Sema::CXXSpecialMember CSM, - bool ConstArg, + CXXSpecialMemberKind CSM, bool ConstArg, Sema::TrivialABIHandling TAH, bool Diagnose) { for (const auto *FI : RD->fields()) { @@ -10119,7 +10150,8 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, // A default constructor is trivial if [...] // -- no non-static data member of its class has a // brace-or-equal-initializer - if (CSM == Sema::CXXDefaultConstructor && FI->hasInClassInitializer()) { + if (CSM == CXXSpecialMemberKind::DefaultConstructor && + FI->hasInClassInitializer()) { if (Diagnose) S.Diag(FI->getLocation(), diag::note_nontrivial_default_member_init) << FI; @@ -10148,10 +10180,12 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, /// Diagnose why the specified class does not have a trivial special member of /// the given kind. -void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) { +void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, + CXXSpecialMemberKind CSM) { QualType Ty = Context.getRecordType(RD); - bool ConstArg = (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment); + bool ConstArg = (CSM == CXXSpecialMemberKind::CopyConstructor || + CSM == CXXSpecialMemberKind::CopyAssignment); checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, ConstArg, CSM, TSK_CompleteObject, TAH_IgnoreTrivialABI, /*Diagnose*/true); @@ -10160,9 +10194,10 @@ void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) { /// Determine whether a defaulted or deleted special member function is trivial, /// as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12, /// C++11 [class.copy]p25, and C++11 [class.dtor]p5. -bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, +bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMemberKind CSM, TrivialABIHandling TAH, bool Diagnose) { - assert(!MD->isUserProvided() && CSM != CXXInvalid && "not special enough"); + assert(!MD->isUserProvided() && CSM != CXXSpecialMemberKind::Invalid && + "not special enough"); CXXRecordDecl *RD = MD->getParent(); @@ -10172,13 +10207,13 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, // A [special member] is trivial if [...] its parameter-type-list is // equivalent to the parameter-type-list of an implicit declaration [...] switch (CSM) { - case CXXDefaultConstructor: - case CXXDestructor: + case CXXSpecialMemberKind::DefaultConstructor: + case CXXSpecialMemberKind::Destructor: // Trivial default constructors and destructors cannot have parameters. break; - case CXXCopyConstructor: - case CXXCopyAssignment: { + case CXXSpecialMemberKind::CopyConstructor: + case CXXSpecialMemberKind::CopyAssignment: { const ParmVarDecl *Param0 = MD->getNonObjectParameter(0); const ReferenceType *RT = Param0->getType()->getAs(); @@ -10207,8 +10242,8 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, break; } - case CXXMoveConstructor: - case CXXMoveAssignment: { + case CXXSpecialMemberKind::MoveConstructor: + case CXXSpecialMemberKind::MoveAssignment: { // Trivial move operations always have non-cv-qualified parameters. const ParmVarDecl *Param0 = MD->getNonObjectParameter(0); const RValueReferenceType *RT = @@ -10223,7 +10258,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, break; } - case CXXInvalid: + case CXXSpecialMemberKind::Invalid: llvm_unreachable("not a special member"); } @@ -10272,7 +10307,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, // C++11 [class.dtor]p5: // A destructor is trivial if [...] // -- the destructor is not virtual - if (CSM == CXXDestructor && MD->isVirtual()) { + if (CSM == CXXSpecialMemberKind::Destructor && MD->isVirtual()) { if (Diagnose) Diag(MD->getLocation(), diag::note_nontrivial_virtual_dtor) << RD; return false; @@ -10281,7 +10316,8 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25: // A [special member] for class X is trivial if [...] // -- class X has no virtual functions and no virtual base classes - if (CSM != CXXDestructor && MD->getParent()->isDynamicClass()) { + if (CSM != CXXSpecialMemberKind::Destructor && + MD->getParent()->isDynamicClass()) { if (!Diagnose) return false; @@ -13760,7 +13796,7 @@ struct SpecialMemberExceptionSpecInfo Sema::ImplicitExceptionSpecification ExceptSpec; SpecialMemberExceptionSpecInfo(Sema &S, CXXMethodDecl *MD, - Sema::CXXSpecialMember CSM, + CXXSpecialMemberKind CSM, Sema::InheritedConstructorInfo *ICI, SourceLocation Loc) : SpecialMemberVisitor(S, MD, CSM, ICI), Loc(Loc), ExceptSpec(S) {} @@ -13793,7 +13829,8 @@ bool SpecialMemberExceptionSpecInfo::visitBase(CXXBaseSpecifier *Base) { } bool SpecialMemberExceptionSpecInfo::visitField(FieldDecl *FD) { - if (CSM == Sema::CXXDefaultConstructor && FD->hasInClassInitializer()) { + if (CSM == CXXSpecialMemberKind::DefaultConstructor && + FD->hasInClassInitializer()) { Expr *E = FD->getInClassInitializer(); if (!E) // FIXME: It's a little wasteful to build and throw away a @@ -13852,7 +13889,7 @@ ExplicitSpecifier Sema::ActOnExplicitBoolSpecifier(Expr *ExplicitExpr) { static Sema::ImplicitExceptionSpecification ComputeDefaultedSpecialMemberExceptionSpec( - Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, + Sema &S, SourceLocation Loc, CXXMethodDecl *MD, CXXSpecialMemberKind CSM, Sema::InheritedConstructorInfo *ICI) { ComputingExceptionSpec CES(S, MD, Loc); @@ -13902,7 +13939,7 @@ struct DeclaringSpecialMember { Sema::ContextRAII SavedContext; bool WasAlreadyBeingDeclared; - DeclaringSpecialMember(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM) + DeclaringSpecialMember(Sema &S, CXXRecordDecl *RD, CXXSpecialMemberKind CSM) : S(S), D(RD, CSM), SavedContext(S, RD) { WasAlreadyBeingDeclared = !S.SpecialMembersBeingDeclared.insert(D).second; if (WasAlreadyBeingDeclared) @@ -13992,13 +14029,13 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( assert(ClassDecl->needsImplicitDefaultConstructor() && "Should not build implicit default constructor!"); - DeclaringSpecialMember DSM(*this, ClassDecl, CXXDefaultConstructor); + DeclaringSpecialMember DSM(*this, ClassDecl, + CXXSpecialMemberKind::DefaultConstructor); if (DSM.isAlreadyBeingDeclared()) return nullptr; - bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, - CXXDefaultConstructor, - false); + bool Constexpr = defaultedSpecialMemberIsConstexpr( + *this, ClassDecl, CXXSpecialMemberKind::DefaultConstructor, false); // Create the actual constructor declaration. CanQualType ClassType @@ -14020,10 +14057,10 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( setupImplicitSpecialMemberType(DefaultCon, Context.VoidTy, std::nullopt); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXDefaultConstructor, - DefaultCon, - /* ConstRHS */ false, - /* Diagnose */ false); + CUDA().inferTargetForImplicitSpecialMember( + ClassDecl, CXXSpecialMemberKind::DefaultConstructor, DefaultCon, + /* ConstRHS */ false, + /* Diagnose */ false); // We don't need to use SpecialMemberIsTrivial here; triviality for default // constructors is easy to compute. @@ -14035,7 +14072,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, DefaultCon); - if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor)) + if (ShouldDeleteSpecialMember(DefaultCon, + CXXSpecialMemberKind::DefaultConstructor)) SetDeclDeleted(DefaultCon, ClassLoc); if (S) @@ -14127,10 +14165,10 @@ Sema::findInheritingConstructor(SourceLocation Loc, // from which it was inherited. InheritedConstructorInfo ICI(*this, Loc, Shadow); - bool Constexpr = - BaseCtor->isConstexpr() && - defaultedSpecialMemberIsConstexpr(*this, Derived, CXXDefaultConstructor, - false, BaseCtor, &ICI); + bool Constexpr = BaseCtor->isConstexpr() && + defaultedSpecialMemberIsConstexpr( + *this, Derived, CXXSpecialMemberKind::DefaultConstructor, + false, BaseCtor, &ICI); CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create( Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo, @@ -14174,7 +14212,8 @@ Sema::findInheritingConstructor(SourceLocation Loc, DerivedCtor->setParams(ParamDecls); Derived->addDecl(DerivedCtor); - if (ShouldDeleteSpecialMember(DerivedCtor, CXXDefaultConstructor, &ICI)) + if (ShouldDeleteSpecialMember(DerivedCtor, + CXXSpecialMemberKind::DefaultConstructor, &ICI)) SetDeclDeleted(DerivedCtor, UsingLoc); return DerivedCtor; @@ -14183,8 +14222,9 @@ Sema::findInheritingConstructor(SourceLocation Loc, void Sema::NoteDeletedInheritingConstructor(CXXConstructorDecl *Ctor) { InheritedConstructorInfo ICI(*this, Ctor->getLocation(), Ctor->getInheritedConstructor().getShadowDecl()); - ShouldDeleteSpecialMember(Ctor, CXXDefaultConstructor, &ICI, - /*Diagnose*/true); + ShouldDeleteSpecialMember(Ctor, CXXSpecialMemberKind::DefaultConstructor, + &ICI, + /*Diagnose*/ true); } void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation, @@ -14275,13 +14315,13 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { // inline public member of its class. assert(ClassDecl->needsImplicitDestructor()); - DeclaringSpecialMember DSM(*this, ClassDecl, CXXDestructor); + DeclaringSpecialMember DSM(*this, ClassDecl, + CXXSpecialMemberKind::Destructor); if (DSM.isAlreadyBeingDeclared()) return nullptr; - bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, - CXXDestructor, - false); + bool Constexpr = defaultedSpecialMemberIsConstexpr( + *this, ClassDecl, CXXSpecialMemberKind::Destructor, false); // Create the actual destructor declaration. CanQualType ClassType @@ -14303,10 +14343,10 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { setupImplicitSpecialMemberType(Destructor, Context.VoidTy, std::nullopt); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXDestructor, - Destructor, - /* ConstRHS */ false, - /* Diagnose */ false); + CUDA().inferTargetForImplicitSpecialMember( + ClassDecl, CXXSpecialMemberKind::Destructor, Destructor, + /* ConstRHS */ false, + /* Diagnose */ false); // We don't need to use SpecialMemberIsTrivial here; triviality for // destructors is easy to compute. @@ -14324,7 +14364,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { // the definition of the class, because its validity depends on the alignment // of the class. We'll check this from ActOnFields once the class is complete. if (ClassDecl->isCompleteDefinition() && - ShouldDeleteSpecialMember(Destructor, CXXDestructor)) + ShouldDeleteSpecialMember(Destructor, CXXSpecialMemberKind::Destructor)) SetDeclDeleted(Destructor, ClassLoc); // Introduce this destructor into its scope. @@ -14905,7 +14945,8 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { // operators taking an object instead of a reference are allowed. assert(ClassDecl->needsImplicitCopyAssignment()); - DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyAssignment); + DeclaringSpecialMember DSM(*this, ClassDecl, + CXXSpecialMemberKind::CopyAssignment); if (DSM.isAlreadyBeingDeclared()) return nullptr; @@ -14922,9 +14963,8 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { ArgType = Context.getLValueReferenceType(ArgType); - bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, - CXXCopyAssignment, - Const); + bool Constexpr = defaultedSpecialMemberIsConstexpr( + *this, ClassDecl, CXXSpecialMemberKind::CopyAssignment, Const); // An implicitly-declared copy assignment operator is an inline public // member of its class. @@ -14945,10 +14985,10 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { setupImplicitSpecialMemberType(CopyAssignment, RetType, ArgType); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXCopyAssignment, - CopyAssignment, - /* ConstRHS */ Const, - /* Diagnose */ false); + CUDA().inferTargetForImplicitSpecialMember( + ClassDecl, CXXSpecialMemberKind::CopyAssignment, CopyAssignment, + /* ConstRHS */ Const, + /* Diagnose */ false); // Add the parameter to the operator. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, @@ -14959,9 +14999,10 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { CopyAssignment->setParams(FromParam); CopyAssignment->setTrivial( - ClassDecl->needsOverloadResolutionForCopyAssignment() - ? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment) - : ClassDecl->hasTrivialCopyAssignment()); + ClassDecl->needsOverloadResolutionForCopyAssignment() + ? SpecialMemberIsTrivial(CopyAssignment, + CXXSpecialMemberKind::CopyAssignment) + : ClassDecl->hasTrivialCopyAssignment()); // Note that we have added this copy-assignment operator. ++getASTContext().NumImplicitCopyAssignmentOperatorsDeclared; @@ -14969,7 +15010,8 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, CopyAssignment); - if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment)) { + if (ShouldDeleteSpecialMember(CopyAssignment, + CXXSpecialMemberKind::CopyAssignment)) { ClassDecl->setImplicitCopyAssignmentIsDeleted(); SetDeclDeleted(CopyAssignment, ClassLoc); } @@ -15256,7 +15298,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { assert(ClassDecl->needsImplicitMoveAssignment()); - DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment); + DeclaringSpecialMember DSM(*this, ClassDecl, + CXXSpecialMemberKind::MoveAssignment); if (DSM.isAlreadyBeingDeclared()) return nullptr; @@ -15272,9 +15315,8 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { QualType RetType = Context.getLValueReferenceType(ArgType); ArgType = Context.getRValueReferenceType(ArgType); - bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, - CXXMoveAssignment, - false); + bool Constexpr = defaultedSpecialMemberIsConstexpr( + *this, ClassDecl, CXXSpecialMemberKind::MoveAssignment, false); // An implicitly-declared move assignment operator is an inline public // member of its class. @@ -15295,10 +15337,10 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { setupImplicitSpecialMemberType(MoveAssignment, RetType, ArgType); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXMoveAssignment, - MoveAssignment, - /* ConstRHS */ false, - /* Diagnose */ false); + CUDA().inferTargetForImplicitSpecialMember( + ClassDecl, CXXSpecialMemberKind::MoveAssignment, MoveAssignment, + /* ConstRHS */ false, + /* Diagnose */ false); // Add the parameter to the operator. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment, @@ -15309,9 +15351,10 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { MoveAssignment->setParams(FromParam); MoveAssignment->setTrivial( - ClassDecl->needsOverloadResolutionForMoveAssignment() - ? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment) - : ClassDecl->hasTrivialMoveAssignment()); + ClassDecl->needsOverloadResolutionForMoveAssignment() + ? SpecialMemberIsTrivial(MoveAssignment, + CXXSpecialMemberKind::MoveAssignment) + : ClassDecl->hasTrivialMoveAssignment()); // Note that we have added this copy-assignment operator. ++getASTContext().NumImplicitMoveAssignmentOperatorsDeclared; @@ -15319,7 +15362,8 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, MoveAssignment); - if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) { + if (ShouldDeleteSpecialMember(MoveAssignment, + CXXSpecialMemberKind::MoveAssignment)) { ClassDecl->setImplicitMoveAssignmentIsDeleted(); SetDeclDeleted(MoveAssignment, ClassLoc); } @@ -15368,10 +15412,10 @@ static void checkMoveAssignmentForRepeatedMove(Sema &S, CXXRecordDecl *Class, // If we're not actually going to call a move assignment for this base, // or the selected move assignment is trivial, skip it. Sema::SpecialMemberOverloadResult SMOR = - S.LookupSpecialMember(Base, Sema::CXXMoveAssignment, - /*ConstArg*/false, /*VolatileArg*/false, - /*RValueThis*/true, /*ConstThis*/false, - /*VolatileThis*/false); + S.LookupSpecialMember(Base, CXXSpecialMemberKind::MoveAssignment, + /*ConstArg*/ false, /*VolatileArg*/ false, + /*RValueThis*/ true, /*ConstThis*/ false, + /*VolatileThis*/ false); if (!SMOR.getMethod() || SMOR.getMethod()->isTrivial() || !SMOR.getMethod()->isMoveAssignmentOperator()) continue; @@ -15648,7 +15692,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( // constructor, one is declared implicitly. assert(ClassDecl->needsImplicitCopyConstructor()); - DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyConstructor); + DeclaringSpecialMember DSM(*this, ClassDecl, + CXXSpecialMemberKind::CopyConstructor); if (DSM.isAlreadyBeingDeclared()) return nullptr; @@ -15666,9 +15711,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( ArgType = Context.getLValueReferenceType(ArgType); - bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, - CXXCopyConstructor, - Const); + bool Constexpr = defaultedSpecialMemberIsConstexpr( + *this, ClassDecl, CXXSpecialMemberKind::CopyConstructor, Const); DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( @@ -15691,10 +15735,10 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( setupImplicitSpecialMemberType(CopyConstructor, Context.VoidTy, ArgType); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXCopyConstructor, - CopyConstructor, - /* ConstRHS */ Const, - /* Diagnose */ false); + CUDA().inferTargetForImplicitSpecialMember( + ClassDecl, CXXSpecialMemberKind::CopyConstructor, CopyConstructor, + /* ConstRHS */ Const, + /* Diagnose */ false); // During template instantiation of special member functions we need a // reliable TypeSourceInfo for the parameter types in order to allow functions @@ -15712,14 +15756,16 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( CopyConstructor->setTrivial( ClassDecl->needsOverloadResolutionForCopyConstructor() - ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor) + ? SpecialMemberIsTrivial(CopyConstructor, + CXXSpecialMemberKind::CopyConstructor) : ClassDecl->hasTrivialCopyConstructor()); CopyConstructor->setTrivialForCall( ClassDecl->hasAttr() || (ClassDecl->needsOverloadResolutionForCopyConstructor() - ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor, - TAH_ConsiderTrivialABI) + ? SpecialMemberIsTrivial(CopyConstructor, + CXXSpecialMemberKind::CopyConstructor, + TAH_ConsiderTrivialABI) : ClassDecl->hasTrivialCopyConstructorForCall())); // Note that we have declared this constructor. @@ -15728,7 +15774,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, CopyConstructor); - if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) { + if (ShouldDeleteSpecialMember(CopyConstructor, + CXXSpecialMemberKind::CopyConstructor)) { ClassDecl->setImplicitCopyConstructorIsDeleted(); SetDeclDeleted(CopyConstructor, ClassLoc); } @@ -15793,7 +15840,8 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( CXXRecordDecl *ClassDecl) { assert(ClassDecl->needsImplicitMoveConstructor()); - DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor); + DeclaringSpecialMember DSM(*this, ClassDecl, + CXXSpecialMemberKind::MoveConstructor); if (DSM.isAlreadyBeingDeclared()) return nullptr; @@ -15807,9 +15855,8 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( ArgType = Context.getAddrSpaceQualType(ClassType, AS); ArgType = Context.getRValueReferenceType(ArgType); - bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, - CXXMoveConstructor, - false); + bool Constexpr = defaultedSpecialMemberIsConstexpr( + *this, ClassDecl, CXXSpecialMemberKind::MoveConstructor, false); DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( @@ -15833,10 +15880,10 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( setupImplicitSpecialMemberType(MoveConstructor, Context.VoidTy, ArgType); if (getLangOpts().CUDA) - inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXMoveConstructor, - MoveConstructor, - /* ConstRHS */ false, - /* Diagnose */ false); + CUDA().inferTargetForImplicitSpecialMember( + ClassDecl, CXXSpecialMemberKind::MoveConstructor, MoveConstructor, + /* ConstRHS */ false, + /* Diagnose */ false); // Add the parameter to the constructor. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor, @@ -15848,13 +15895,15 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( MoveConstructor->setTrivial( ClassDecl->needsOverloadResolutionForMoveConstructor() - ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor) + ? SpecialMemberIsTrivial(MoveConstructor, + CXXSpecialMemberKind::MoveConstructor) : ClassDecl->hasTrivialMoveConstructor()); MoveConstructor->setTrivialForCall( ClassDecl->hasAttr() || (ClassDecl->needsOverloadResolutionForMoveConstructor() - ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor, + ? SpecialMemberIsTrivial(MoveConstructor, + CXXSpecialMemberKind::MoveConstructor, TAH_ConsiderTrivialABI) : ClassDecl->hasTrivialMoveConstructorForCall())); @@ -15864,7 +15913,8 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, MoveConstructor); - if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) { + if (ShouldDeleteSpecialMember(MoveConstructor, + CXXSpecialMemberKind::MoveConstructor)) { ClassDecl->setImplicitMoveConstructorIsDeleted(); SetDeclDeleted(MoveConstructor, ClassLoc); } @@ -16136,7 +16186,7 @@ ExprResult Sema::BuildCXXConstructExpr( DeclInitType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) && "given constructor for wrong type"); MarkFunctionReferenced(ConstructLoc, Constructor); - if (getLangOpts().CUDA && !CheckCUDACall(ConstructLoc, Constructor)) + if (getLangOpts().CUDA && !CUDA().CheckCall(ConstructLoc, Constructor)) return ExprError(); return CheckForImmediateInvocation( @@ -18110,7 +18160,8 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, return ND; } -void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { +void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc, + StringLiteral *Message) { AdjustDeclIfTemplate(Dcl); FunctionDecl *Fn = dyn_cast_or_null(Dcl); @@ -18159,7 +18210,7 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { // C++11 [dcl.fct.def.delete]p4: // A deleted function is implicitly inline. Fn->setImplicitlyInline(); - Fn->setDeletedAsWritten(); + Fn->setDeletedAsWritten(true, Message); } void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { @@ -18272,11 +18323,11 @@ void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) { } } -void Sema::SetFunctionBodyKind(Decl *D, SourceLocation Loc, - FnBodyKind BodyKind) { +void Sema::SetFunctionBodyKind(Decl *D, SourceLocation Loc, FnBodyKind BodyKind, + StringLiteral *DeletedMessage) { switch (BodyKind) { case FnBodyKind::Delete: - SetDeclDeleted(D, Loc); + SetDeclDeleted(D, Loc, DeletedMessage); break; case FnBodyKind::Default: SetDeclDefaulted(D, Loc); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 846e7d5d3ab92b7ef6d1fb13aee536bf53c0961f..189764cb4b6b08d66f8b26ee57026b695065cf0e 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -49,10 +49,12 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaFixItUtils.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ConvertUTF.h" @@ -271,8 +273,11 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, Diag(Loc, diag::err_deleted_inherited_ctor_use) << Ctor->getParent() << Ctor->getInheritedConstructor().getConstructor()->getParent(); - else - Diag(Loc, diag::err_deleted_function_use); + else { + StringLiteral *Msg = FD->getDeletedMessage(); + Diag(Loc, diag::err_deleted_function_use) + << (Msg != nullptr) << (Msg ? Msg->getString() : StringRef()); + } NoteDeletedFunction(FD); return true; } @@ -307,7 +312,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, DeduceReturnType(FD, Loc)) return true; - if (getLangOpts().CUDA && !CheckCUDACall(Loc, FD)) + if (getLangOpts().CUDA && !CUDA().CheckCall(Loc, FD)) return true; } @@ -2912,9 +2917,26 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // to get this right here so that we don't end up making a // spuriously dependent expression if we're inside a dependent // instance method. - if (isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand)) - return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, - S); + if (getLangOpts().CPlusPlus && !R.empty() && + (*R.begin())->isCXXClassMember()) { + bool MightBeImplicitMember; + if (!IsAddressOfOperand) + MightBeImplicitMember = true; + else if (!SS.isEmpty()) + MightBeImplicitMember = false; + else if (R.isOverloadedResult()) + MightBeImplicitMember = false; + else if (R.isUnresolvableResult()) + MightBeImplicitMember = true; + else + MightBeImplicitMember = isa(R.getFoundDecl()) || + isa(R.getFoundDecl()) || + isa(R.getFoundDecl()); + + if (MightBeImplicitMember) + return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, + R, TemplateArgs, S); + } if (TemplateArgs || TemplateKWLoc.isValid()) { @@ -3425,11 +3447,10 @@ static bool ShouldLookupResultBeMultiVersionOverload(const LookupResult &R) { ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, - bool AcceptInvalidDecl, - bool NeedUnresolved) { + bool AcceptInvalidDecl) { // If this is a single, fully-resolved result and we don't need ADL, // just build an ordinary singleton decl ref. - if (!NeedUnresolved && !NeedsADL && R.isSingleResult() && + if (!NeedsADL && R.isSingleResult() && !R.getAsSingle() && !ShouldLookupResultBeMultiVersionOverload(R)) return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(), @@ -6293,7 +6314,6 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, // Pass down lifetime extending flag, and collect temporaries in // CreateMaterializeTemporaryExpr when we rewrite the call argument. keepInLifetimeExtendingContext(); - keepInMaterializeTemporaryObjectContext(); EnsureImmediateInvocationInDefaultArgs Immediate(*this); ExprResult Res; runWithSufficientStackSpace(CallLoc, [&] { @@ -7719,7 +7739,8 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, } if (CXXMethodDecl *Method = dyn_cast_or_null(FDecl)) - if (Method->isImplicitObjectMemberFunction()) + if (!isa(CurContext) && + Method->isImplicitObjectMemberFunction()) return ExprError(Diag(LParenLoc, diag::err_member_call_without_object) << Fn->getSourceRange() << 0); @@ -14858,8 +14879,8 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, return QualType(); } else if (ResType->isAnyComplexType()) { // C99 does not support ++/-- on complex types, we allow as an extension. - S.Diag(OpLoc, diag::ext_integer_increment_complex) - << ResType << Op->getSourceRange(); + S.Diag(OpLoc, diag::ext_increment_complex) + << IsInc << Op->getSourceRange(); } else if (ResType->isPlaceholderType()) { ExprResult PR = S.CheckPlaceholderExpr(Op); if (PR.isInvalid()) return QualType(); @@ -17306,8 +17327,9 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, // CUDA device code does not support varargs. if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) { if (const FunctionDecl *F = dyn_cast(CurContext)) { - CUDAFunctionTarget T = IdentifyCUDATarget(F); - if (T == CFT_Global || T == CFT_Device || T == CFT_HostDevice) + CUDAFunctionTarget T = CUDA().IdentifyTarget(F); + if (T == CUDAFunctionTarget::Global || T == CUDAFunctionTarget::Device || + T == CUDAFunctionTarget::HostDevice) return ExprError(Diag(E->getBeginLoc(), diag::err_va_arg_in_device)); } } @@ -18657,9 +18679,9 @@ void Sema::PopExpressionEvaluationContext() { // Append the collected materialized temporaries into previous context before // exit if the previous also is a lifetime extending context. auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2]; - if (getLangOpts().CPlusPlus23 && isInLifetimeExtendingContext() && - PrevRecord.InLifetimeExtendingContext && !ExprEvalContexts.empty()) { - auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2]; + if (getLangOpts().CPlusPlus23 && Rec.InLifetimeExtendingContext && + PrevRecord.InLifetimeExtendingContext && + !Rec.ForRangeLifetimeExtendTemps.empty()) { PrevRecord.ForRangeLifetimeExtendTemps.append( Rec.ForRangeLifetimeExtendTemps); } @@ -18959,7 +18981,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, checkSpecializationReachability(Loc, Func); if (getLangOpts().CUDA) - CheckCUDACall(Loc, Func); + CUDA().CheckCall(Loc, Func); // If we need a definition, try to create one. if (NeedDefinition && !Func->getBody()) { @@ -19106,7 +19128,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, // side. Therefore keep trying until it is recorded. if (LangOpts.OffloadImplicitHostDeviceTemplates && LangOpts.CUDAIsDevice && !getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(Func)) - CUDARecordImplicitHostDeviceFuncUsedByDevice(Func); + CUDA().RecordImplicitHostDeviceFuncUsedByDevice(Func); // If this is the first "real" use, act on that. if (OdrUse == OdrUseContext::Used && !Func->isUsed(/*CheckUsedAttr=*/false)) { @@ -19179,26 +19201,28 @@ MarkVarDeclODRUsed(ValueDecl *V, SourceLocation Loc, Sema &SemaRef, if (SemaRef.LangOpts.CUDA && Var->hasGlobalStorage()) { auto *FD = dyn_cast_or_null(SemaRef.CurContext); - auto VarTarget = SemaRef.IdentifyCUDATarget(Var); - auto UserTarget = SemaRef.IdentifyCUDATarget(FD); - if (VarTarget == Sema::CVT_Host && - (UserTarget == Sema::CFT_Device || UserTarget == Sema::CFT_HostDevice || - UserTarget == Sema::CFT_Global)) { + auto VarTarget = SemaRef.CUDA().IdentifyTarget(Var); + auto UserTarget = SemaRef.CUDA().IdentifyTarget(FD); + if (VarTarget == SemaCUDA::CVT_Host && + (UserTarget == CUDAFunctionTarget::Device || + UserTarget == CUDAFunctionTarget::HostDevice || + UserTarget == CUDAFunctionTarget::Global)) { // Diagnose ODR-use of host global variables in device functions. // Reference of device global variables in host functions is allowed // through shadow variables therefore it is not diagnosed. if (SemaRef.LangOpts.CUDAIsDevice && !SemaRef.LangOpts.HIPStdPar) { SemaRef.targetDiag(Loc, diag::err_ref_bad_target) - << /*host*/ 2 << /*variable*/ 1 << Var << UserTarget; + << /*host*/ 2 << /*variable*/ 1 << Var + << llvm::to_underlying(UserTarget); SemaRef.targetDiag(Var->getLocation(), Var->getType().isConstQualified() ? diag::note_cuda_const_var_unpromoted : diag::note_cuda_host_var); } - } else if (VarTarget == Sema::CVT_Device && + } else if (VarTarget == SemaCUDA::CVT_Device && !Var->hasAttr() && - (UserTarget == Sema::CFT_Host || - UserTarget == Sema::CFT_HostDevice)) { + (UserTarget == CUDAFunctionTarget::Host || + UserTarget == CUDAFunctionTarget::HostDevice)) { // Record a CUDA/HIP device side variable if it is ODR-used // by host code. This is done conservatively, when the variable is // referenced in any of the following contexts: @@ -20704,7 +20728,7 @@ static void FixDependencyOfIdExpressionsInLambdaWithDependentObjectParameter( if (MD->getType().isNull()) continue; - const auto *Ty = cast(MD->getType()); + const auto *Ty = MD->getType()->getAs(); if (!Ty || !MD->isExplicitObjectMemberFunction() || !Ty->getParamType(0)->isDependentType()) continue; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 763901d4418d20c587a3fb6768c2730401c2229c..74ed3fe7bd5201f331ed0895161cd5f7337dbcde 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -38,12 +38,14 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaLambda.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TypeSize.h" @@ -883,8 +885,8 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, // Exceptions aren't allowed in CUDA device code. if (getLangOpts().CUDA) - CUDADiagIfDeviceCode(OpLoc, diag::err_cuda_device_exceptions) - << "throw" << CurrentCUDATarget(); + CUDA().DiagIfDeviceCode(OpLoc, diag::err_cuda_device_exceptions) + << "throw" << llvm::to_underlying(CUDA().CurrentTarget()); if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope()) Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw"; @@ -1414,42 +1416,26 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, } ExprResult Sema::ActOnCXXThis(SourceLocation Loc) { - // C++20 [expr.prim.this]p1: - // The keyword this names a pointer to the object for which an - // implicit object member function is invoked or a non-static - // data member's initializer is evaluated. + /// C++ 9.3.2: In the body of a non-static member function, the keyword this + /// is a non-lvalue expression whose value is the address of the object for + /// which the function is called. QualType ThisTy = getCurrentThisType(); - if (CheckCXXThisType(Loc, ThisTy)) - return ExprError(); + if (ThisTy.isNull()) { + DeclContext *DC = getFunctionLevelDeclContext(); - return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false); -} + if (const auto *Method = dyn_cast(DC); + Method && Method->isExplicitObjectMemberFunction()) { + return Diag(Loc, diag::err_invalid_this_use) << 1; + } -bool Sema::CheckCXXThisType(SourceLocation Loc, QualType Type) { - if (!Type.isNull()) - return false; + if (isLambdaCallWithExplicitObjectParameter(CurContext)) + return Diag(Loc, diag::err_invalid_this_use) << 1; - // C++20 [expr.prim.this]p3: - // If a declaration declares a member function or member function template - // of a class X, the expression this is a prvalue of type - // "pointer to cv-qualifier-seq X" wherever X is the current class between - // the optional cv-qualifier-seq and the end of the function-definition, - // member-declarator, or declarator. It shall not appear within the - // declaration of either a static member function or an explicit object - // member function of the current class (although its type and value - // category are defined within such member functions as they are within - // an implicit object member function). - DeclContext *DC = getFunctionLevelDeclContext(); - if (const auto *Method = dyn_cast(DC); - Method && Method->isExplicitObjectMemberFunction()) { - Diag(Loc, diag::err_invalid_this_use) << 1; - } else if (isLambdaCallWithExplicitObjectParameter(CurContext)) { - Diag(Loc, diag::err_invalid_this_use) << 1; - } else { - Diag(Loc, diag::err_invalid_this_use) << 0; + return Diag(Loc, diag::err_invalid_this_use) << 0; } - return true; + + return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false); } Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type, @@ -1488,7 +1474,7 @@ void Sema::MarkThisReferenced(CXXThisExpr *This) { if (MD->getType().isNull()) return false; - const auto *Ty = cast(MD->getType()); + const auto *Ty = MD->getType()->getAs(); return Ty && MD->isExplicitObjectMemberFunction() && Ty->getParamType(0)->isDependentType(); } @@ -1707,17 +1693,17 @@ bool Sema::isUsualDeallocationFunction(const CXXMethodDecl *Method) { // [CUDA] Ignore this function, if we can't call it. const FunctionDecl *Caller = getCurFunctionDecl(/*AllowLambda=*/true); if (getLangOpts().CUDA) { - auto CallPreference = IdentifyCUDAPreference(Caller, Method); + auto CallPreference = CUDA().IdentifyPreference(Caller, Method); // If it's not callable at all, it's not the right function. - if (CallPreference < CFP_WrongSide) + if (CallPreference < SemaCUDA::CFP_WrongSide) return false; - if (CallPreference == CFP_WrongSide) { + if (CallPreference == SemaCUDA::CFP_WrongSide) { // Maybe. We have to check if there are better alternatives. DeclContext::lookup_result R = Method->getDeclContext()->lookup(Method->getDeclName()); for (const auto *D : R) { if (const auto *FD = dyn_cast(D)) { - if (IdentifyCUDAPreference(Caller, FD) > CFP_WrongSide) + if (CUDA().IdentifyPreference(Caller, FD) > SemaCUDA::CFP_WrongSide) return false; } } @@ -1736,7 +1722,7 @@ bool Sema::isUsualDeallocationFunction(const CXXMethodDecl *Method) { return llvm::none_of(PreventedBy, [&](const FunctionDecl *FD) { assert(FD->getNumParams() == 1 && "Only single-operand functions should be in PreventedBy"); - return IdentifyCUDAPreference(Caller, FD) >= CFP_HostDevice; + return CUDA().IdentifyPreference(Caller, FD) >= SemaCUDA::CFP_HostDevice; }); } @@ -1773,7 +1759,7 @@ namespace { UsualDeallocFnInfo(Sema &S, DeclAccessPair Found) : Found(Found), FD(dyn_cast(Found->getUnderlyingDecl())), Destroying(false), HasSizeT(false), HasAlignValT(false), - CUDAPref(Sema::CFP_Native) { + CUDAPref(SemaCUDA::CFP_Native) { // A function template declaration is never a usual deallocation function. if (!FD) return; @@ -1799,7 +1785,7 @@ namespace { // In CUDA, determine how much we'd like / dislike to call this. if (S.getLangOpts().CUDA) - CUDAPref = S.IdentifyCUDAPreference( + CUDAPref = S.CUDA().IdentifyPreference( S.getCurFunctionDecl(/*AllowLambda=*/true), FD); } @@ -1830,7 +1816,7 @@ namespace { DeclAccessPair Found; FunctionDecl *FD; bool Destroying, HasSizeT, HasAlignValT; - Sema::CUDAFunctionPreference CUDAPref; + SemaCUDA::CUDAFunctionPreference CUDAPref; }; } @@ -1854,7 +1840,7 @@ static UsualDeallocFnInfo resolveDeallocationOverload( for (auto I = R.begin(), E = R.end(); I != E; ++I) { UsualDeallocFnInfo Info(S, I.getPair()); if (!Info || !isNonPlacementDeallocationFunction(S, Info.FD) || - Info.CUDAPref == Sema::CFP_Never) + Info.CUDAPref == SemaCUDA::CFP_Never) continue; if (!Best) { @@ -2714,13 +2700,9 @@ static bool resolveAllocationOverload( return true; case OR_Deleted: { - if (Diagnose) { - Candidates.NoteCandidates( - PartialDiagnosticAt(R.getNameLoc(), - S.PDiag(diag::err_ovl_deleted_call) - << R.getLookupName() << Range), - S, OCD_AllCandidates, Args); - } + if (Diagnose) + S.DiagnoseUseOfDeletedFunction(R.getNameLoc(), Range, R.getLookupName(), + Candidates, Best->Function, Args); return true; } } @@ -2955,8 +2937,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, } if (getLangOpts().CUDA) - EraseUnwantedCUDAMatches(getCurFunctionDecl(/*AllowLambda=*/true), - Matches); + CUDA().EraseUnwantedMatches(getCurFunctionDecl(/*AllowLambda=*/true), + Matches); } else { // C++1y [expr.new]p22: // For a non-placement allocation function, the normal deallocation @@ -3374,7 +3356,9 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, // FIXME: DiagnoseUseOfDecl? if (Operator->isDeleted()) { if (Diagnose) { - Diag(StartLoc, diag::err_deleted_function_use); + StringLiteral *Msg = Operator->getDeletedMessage(); + Diag(StartLoc, diag::err_deleted_function_use) + << (Msg != nullptr) << (Msg ? Msg->getString() : StringRef()); NoteDeletedFunction(Operator); } return true; @@ -3978,14 +3962,11 @@ static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall, S, OCD_AmbiguousCandidates, Args); return true; - case OR_Deleted: { - Candidates.NoteCandidates( - PartialDiagnosticAt(R.getNameLoc(), S.PDiag(diag::err_ovl_deleted_call) - << R.getLookupName() << Range), - S, OCD_AllCandidates, Args); + case OR_Deleted: + S.DiagnoseUseOfDeletedFunction(R.getNameLoc(), Range, R.getLookupName(), + Candidates, Best->Function, Args); return true; } - } llvm_unreachable("Unreachable, bad result from BestViableFunction"); } @@ -5010,6 +4991,20 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, return From; } +/// Checks that type T is not a VLA. +/// +/// @returns @c true if @p T is VLA and a diagnostic was emitted, +/// @c false otherwise. +static bool DiagnoseVLAInCXXTypeTrait(Sema &S, const TypeSourceInfo *T, + clang::tok::TokenKind TypeTraitID) { + if (!T->getType()->isVariableArrayType()) + return false; + + S.Diag(T->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported) + << 1 << TypeTraitID; + return true; +} + /// Check the completeness of a type in a unary type trait. /// /// If the particular type trait requires a complete type, tries to complete @@ -5186,7 +5181,9 @@ static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op, } static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, - SourceLocation KeyLoc, QualType T) { + SourceLocation KeyLoc, + TypeSourceInfo *TInfo) { + QualType T = TInfo->getType(); assert(!T->isDependentType() && "Cannot evaluate traits of dependent type"); ASTContext &C = Self.Context; @@ -5203,21 +5200,13 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, case UTT_IsArray: return T->isArrayType(); case UTT_IsBoundedArray: - if (!T->isVariableArrayType()) { - return T->isArrayType() && !T->isIncompleteArrayType(); - } - - Self.Diag(KeyLoc, diag::err_vla_unsupported) - << 1 << tok::kw___is_bounded_array; - return false; + if (DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___is_bounded_array)) + return false; + return T->isArrayType() && !T->isIncompleteArrayType(); case UTT_IsUnboundedArray: - if (!T->isVariableArrayType()) { - return T->isIncompleteArrayType(); - } - - Self.Diag(KeyLoc, diag::err_vla_unsupported) - << 1 << tok::kw___is_unbounded_array; - return false; + if (DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___is_unbounded_array)) + return false; + return T->isIncompleteArrayType(); case UTT_IsPointer: return T->isAnyPointerType(); case UTT_IsNullPointer: @@ -5629,7 +5618,7 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind, return false; if (Kind <= UTT_Last) - return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]->getType()); + return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]); // Evaluate ReferenceBindsToTemporary and ReferenceConstructsFromTemporary // alongside the IsConstructible traits to avoid duplication. @@ -6091,13 +6080,24 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI Self.RequireCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT, diag::err_incomplete_type); - if (LhsT->isVariableArrayType()) - Self.Diag(Lhs->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported) - << 1 << tok::kw___is_layout_compatible; - if (RhsT->isVariableArrayType()) - Self.Diag(Rhs->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported) - << 1 << tok::kw___is_layout_compatible; + DiagnoseVLAInCXXTypeTrait(Self, Lhs, tok::kw___is_layout_compatible); + DiagnoseVLAInCXXTypeTrait(Self, Rhs, tok::kw___is_layout_compatible); + return Self.IsLayoutCompatible(LhsT, RhsT); + } + case BTT_IsPointerInterconvertibleBaseOf: { + if (LhsT->isStructureOrClassType() && RhsT->isStructureOrClassType() && + !Self.getASTContext().hasSameUnqualifiedType(LhsT, RhsT)) { + Self.RequireCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT, + diag::err_incomplete_type); + } + + DiagnoseVLAInCXXTypeTrait(Self, Lhs, + tok::kw___is_pointer_interconvertible_base_of); + DiagnoseVLAInCXXTypeTrait(Self, Rhs, + tok::kw___is_pointer_interconvertible_base_of); + + return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs); } default: llvm_unreachable("not a BTT"); } @@ -8429,7 +8429,7 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) { // unnecessary temporary objects. If we skip this step, IR generation is // able to synthesize the storage for itself in the aggregate case, and // adding the extra node to the AST is just clutter. - if (isInMaterializeTemporaryObjectContext() && getLangOpts().CPlusPlus17 && + if (isInLifetimeExtendingContext() && getLangOpts().CPlusPlus17 && E->isPRValue() && !E->getType()->isVoidType()) { ExprResult Res = TemporaryMaterializationConversion(E); if (Res.isInvalid()) @@ -8642,8 +8642,21 @@ static ExprResult attemptRecovery(Sema &SemaRef, // Detect and handle the case where the decl might be an implicit // member. - if (SemaRef.isPotentialImplicitMemberAccess( - NewSS, R, Consumer.isAddressOfOperand())) + bool MightBeImplicitMember; + if (!Consumer.isAddressOfOperand()) + MightBeImplicitMember = true; + else if (!NewSS.isEmpty()) + MightBeImplicitMember = false; + else if (R.isOverloadedResult()) + MightBeImplicitMember = false; + else if (R.isUnresolvableResult()) + MightBeImplicitMember = true; + else + MightBeImplicitMember = isa(ND) || + isa(ND) || + isa(ND); + + if (MightBeImplicitMember) return SemaRef.BuildPossibleImplicitMemberExpr( NewSS, /*TemplateKWLoc*/ SourceLocation(), R, /*TemplateArgs*/ nullptr, /*S*/ nullptr); diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index eeac753a3489794df316186c32c7051c2d0533c0..32998ae60eafe2b3836b6bf8af40c1fc0d623079 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -61,10 +61,6 @@ enum IMAKind { /// The reference is a contextually-permitted abstract member reference. IMA_Abstract, - /// Whether the context is static is dependent on the enclosing template (i.e. - /// in a dependent class scope explicit specialization). - IMA_Dependent, - /// The reference may be to an unresolved using declaration and the /// context is not an instance method. IMA_Unresolved_StaticOrExplicitContext, @@ -95,18 +91,10 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, DeclContext *DC = SemaRef.getFunctionLevelDeclContext(); - bool couldInstantiateToStatic = false; - bool isStaticOrExplicitContext = SemaRef.CXXThisTypeOverride.isNull(); - - if (auto *MD = dyn_cast(DC)) { - if (MD->isImplicitObjectMemberFunction()) { - isStaticOrExplicitContext = false; - // A dependent class scope function template explicit specialization - // that is neither declared 'static' nor with an explicit object - // parameter could instantiate to a static or non-static member function. - couldInstantiateToStatic = MD->getDependentSpecializationInfo(); - } - } + bool isStaticOrExplicitContext = + SemaRef.CXXThisTypeOverride.isNull() && + (!isa(DC) || cast(DC)->isStatic() || + cast(DC)->isExplicitObjectMemberFunction()); if (R.isUnresolvableResult()) return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext @@ -135,9 +123,6 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, if (Classes.empty()) return IMA_Static; - if (couldInstantiateToStatic) - return IMA_Dependent; - // C++11 [expr.prim.general]p12: // An id-expression that denotes a non-static data member or non-static // member function of a class can only be used: @@ -278,52 +263,32 @@ static void diagnoseInstanceReference(Sema &SemaRef, } } -bool Sema::isPotentialImplicitMemberAccess(const CXXScopeSpec &SS, - LookupResult &R, - bool IsAddressOfOperand) { - if (!getLangOpts().CPlusPlus) - return false; - else if (R.empty() || !R.begin()->isCXXClassMember()) - return false; - else if (!IsAddressOfOperand) - return true; - else if (!SS.isEmpty()) - return false; - else if (R.isOverloadedResult()) - return false; - else if (R.isUnresolvableResult()) - return true; - else - return isa(R.getFoundDecl()); -} - /// Builds an expression which might be an implicit member expression. ExprResult Sema::BuildPossibleImplicitMemberExpr( const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs, const Scope *S) { - switch (IMAKind Classification = ClassifyImplicitMemberAccess(*this, R)) { + const TemplateArgumentListInfo *TemplateArgs, const Scope *S, + UnresolvedLookupExpr *AsULE) { + switch (ClassifyImplicitMemberAccess(*this, R)) { case IMA_Instance: + return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S); + case IMA_Mixed: case IMA_Mixed_Unrelated: case IMA_Unresolved: - return BuildImplicitMemberExpr( - SS, TemplateKWLoc, R, TemplateArgs, - /*IsKnownInstance=*/Classification == IMA_Instance, S); + return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false, + S); + case IMA_Field_Uneval_Context: Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use) << R.getLookupNameInfo().getName(); [[fallthrough]]; case IMA_Static: case IMA_Abstract: - case IMA_Dependent: case IMA_Mixed_StaticOrExplicitContext: case IMA_Unresolved_StaticOrExplicitContext: if (TemplateArgs || TemplateKWLoc.isValid()) - return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*RequiresADL=*/false, - TemplateArgs); - return BuildDeclarationNameExpr( - SS, R, /*NeedsADL=*/false, /*AcceptInvalidDecl=*/false, - /*NeedUnresolved=*/Classification == IMA_Dependent); + return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs); + return AsULE ? AsULE : BuildDeclarationNameExpr(SS, R, false); case IMA_Error_StaticOrExplicitContext: case IMA_Error_Unrelated: diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 681849d6e6c8a2065088e46a8a504cf9f80ac1f8..bb9e37f18d370c38f0cd663e4fb22a9a8ed35df7 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -9,17 +9,25 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaHLSL.h" +#include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Sema/Sema.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/TargetParser/Triple.h" +#include using namespace clang; SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S) {} -Decl *SemaHLSL::ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer, - SourceLocation KwLoc, - IdentifierInfo *Ident, - SourceLocation IdentLoc, - SourceLocation LBrace) { +Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer, + SourceLocation KwLoc, IdentifierInfo *Ident, + SourceLocation IdentLoc, + SourceLocation LBrace) { // For anonymous namespace, take the location of the left brace. DeclContext *LexicalParent = SemaRef.getCurLexicalContext(); HLSLBufferDecl *Result = HLSLBufferDecl::Create( @@ -31,8 +39,174 @@ Decl *SemaHLSL::ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer, return Result; } -void SemaHLSL::ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace) { +void SemaHLSL::ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace) { auto *BufDecl = cast(Dcl); BufDecl->setRBraceLoc(RBrace); SemaRef.PopDeclContext(); } + +HLSLNumThreadsAttr *SemaHLSL::mergeNumThreadsAttr(Decl *D, + const AttributeCommonInfo &AL, + int X, int Y, int Z) { + if (HLSLNumThreadsAttr *NT = D->getAttr()) { + if (NT->getX() != X || NT->getY() != Y || NT->getZ() != Z) { + Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL; + Diag(AL.getLoc(), diag::note_conflicting_attribute); + } + return nullptr; + } + return ::new (getASTContext()) + HLSLNumThreadsAttr(getASTContext(), AL, X, Y, Z); +} + +HLSLShaderAttr * +SemaHLSL::mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, + HLSLShaderAttr::ShaderType ShaderType) { + if (HLSLShaderAttr *NT = D->getAttr()) { + if (NT->getType() != ShaderType) { + Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL; + Diag(AL.getLoc(), diag::note_conflicting_attribute); + } + return nullptr; + } + return HLSLShaderAttr::Create(getASTContext(), ShaderType, AL); +} + +HLSLParamModifierAttr * +SemaHLSL::mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, + HLSLParamModifierAttr::Spelling Spelling) { + // We can only merge an `in` attribute with an `out` attribute. All other + // combinations of duplicated attributes are ill-formed. + if (HLSLParamModifierAttr *PA = D->getAttr()) { + if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) || + (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) { + D->dropAttr(); + SourceRange AdjustedRange = {PA->getLocation(), AL.getRange().getEnd()}; + return HLSLParamModifierAttr::Create( + getASTContext(), /*MergedSpelling=*/true, AdjustedRange, + HLSLParamModifierAttr::Keyword_inout); + } + Diag(AL.getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL; + Diag(PA->getLocation(), diag::note_conflicting_attribute); + return nullptr; + } + return HLSLParamModifierAttr::Create(getASTContext(), AL); +} + +void SemaHLSL::ActOnTopLevelFunction(FunctionDecl *FD) { + auto &TargetInfo = getASTContext().getTargetInfo(); + + if (FD->getName() != TargetInfo.getTargetOpts().HLSLEntry) + return; + + StringRef Env = TargetInfo.getTriple().getEnvironmentName(); + HLSLShaderAttr::ShaderType ShaderType; + if (HLSLShaderAttr::ConvertStrToShaderType(Env, ShaderType)) { + if (const auto *Shader = FD->getAttr()) { + // The entry point is already annotated - check that it matches the + // triple. + if (Shader->getType() != ShaderType) { + Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch) + << Shader; + FD->setInvalidDecl(); + } + } else { + // Implicitly add the shader attribute if the entry function isn't + // explicitly annotated. + FD->addAttr(HLSLShaderAttr::CreateImplicit(getASTContext(), ShaderType, + FD->getBeginLoc())); + } + } else { + switch (TargetInfo.getTriple().getEnvironment()) { + case llvm::Triple::UnknownEnvironment: + case llvm::Triple::Library: + break; + default: + llvm_unreachable("Unhandled environment in triple"); + } + } +} + +void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) { + const auto *ShaderAttr = FD->getAttr(); + assert(ShaderAttr && "Entry point has no shader attribute"); + HLSLShaderAttr::ShaderType ST = ShaderAttr->getType(); + + switch (ST) { + case HLSLShaderAttr::Pixel: + case HLSLShaderAttr::Vertex: + case HLSLShaderAttr::Geometry: + case HLSLShaderAttr::Hull: + case HLSLShaderAttr::Domain: + case HLSLShaderAttr::RayGeneration: + case HLSLShaderAttr::Intersection: + case HLSLShaderAttr::AnyHit: + case HLSLShaderAttr::ClosestHit: + case HLSLShaderAttr::Miss: + case HLSLShaderAttr::Callable: + if (const auto *NT = FD->getAttr()) { + DiagnoseAttrStageMismatch(NT, ST, + {HLSLShaderAttr::Compute, + HLSLShaderAttr::Amplification, + HLSLShaderAttr::Mesh}); + FD->setInvalidDecl(); + } + break; + + case HLSLShaderAttr::Compute: + case HLSLShaderAttr::Amplification: + case HLSLShaderAttr::Mesh: + if (!FD->hasAttr()) { + Diag(FD->getLocation(), diag::err_hlsl_missing_numthreads) + << HLSLShaderAttr::ConvertShaderTypeToStr(ST); + FD->setInvalidDecl(); + } + break; + } + + for (ParmVarDecl *Param : FD->parameters()) { + if (const auto *AnnotationAttr = Param->getAttr()) { + CheckSemanticAnnotation(FD, Param, AnnotationAttr); + } else { + // FIXME: Handle struct parameters where annotations are on struct fields. + // See: https://github.com/llvm/llvm-project/issues/57875 + Diag(FD->getLocation(), diag::err_hlsl_missing_semantic_annotation); + Diag(Param->getLocation(), diag::note_previous_decl) << Param; + FD->setInvalidDecl(); + } + } + // FIXME: Verify return type semantic annotation. +} + +void SemaHLSL::CheckSemanticAnnotation( + FunctionDecl *EntryPoint, const Decl *Param, + const HLSLAnnotationAttr *AnnotationAttr) { + auto *ShaderAttr = EntryPoint->getAttr(); + assert(ShaderAttr && "Entry point has no shader attribute"); + HLSLShaderAttr::ShaderType ST = ShaderAttr->getType(); + + switch (AnnotationAttr->getKind()) { + case attr::HLSLSV_DispatchThreadID: + case attr::HLSLSV_GroupIndex: + if (ST == HLSLShaderAttr::Compute) + return; + DiagnoseAttrStageMismatch(AnnotationAttr, ST, {HLSLShaderAttr::Compute}); + break; + default: + llvm_unreachable("Unknown HLSLAnnotationAttr"); + } +} + +void SemaHLSL::DiagnoseAttrStageMismatch( + const Attr *A, HLSLShaderAttr::ShaderType Stage, + std::initializer_list AllowedStages) { + SmallVector StageStrings; + llvm::transform(AllowedStages, std::back_inserter(StageStrings), + [](HLSLShaderAttr::ShaderType ST) { + return StringRef( + HLSLShaderAttr::ConvertShaderTypeToStr(ST)); + }); + Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage) + << A << HLSLShaderAttr::ConvertShaderTypeToStr(Stage) + << (AllowedStages.size() != 1) << join(StageStrings, ", "); +} diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index a75e9925a431468e6dfbeca50fae10c01dc07fe7..fb7a80ab02846cd078c64bccf7b3ba9f19360d1a 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -31,6 +31,7 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" @@ -9762,12 +9763,15 @@ bool InitializationSequence::Diagnose(Sema &S, break; } case OR_Deleted: { - S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function) - << OnlyArg->getType() << DestType.getNonReferenceType() - << Args[0]->getSourceRange(); OverloadCandidateSet::iterator Best; OverloadingResult Ovl = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best); + + StringLiteral *Msg = Best->Function->getDeletedMessage(); + S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function) + << OnlyArg->getType() << DestType.getNonReferenceType() + << (Msg != nullptr) << (Msg ? Msg->getString() : StringRef()) + << Args[0]->getSourceRange(); if (Ovl == OR_Deleted) { S.NoteDeletedFunction(Best->Function); } else { @@ -10023,11 +10027,15 @@ bool InitializationSequence::Diagnose(Sema &S, // implicit. if (S.isImplicitlyDeleted(Best->Function)) S.Diag(Kind.getLocation(), diag::err_ovl_deleted_special_init) - << S.getSpecialMember(cast(Best->Function)) - << DestType << ArgsRange; - else - S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init) + << llvm::to_underlying( + S.getSpecialMember(cast(Best->Function))) << DestType << ArgsRange; + else { + StringLiteral *Msg = Best->Function->getDeletedMessage(); + S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init) + << DestType << (Msg != nullptr) + << (Msg ? Msg->getString() : StringRef()) << ArgsRange; + } S.NoteDeletedFunction(Best->Function); break; @@ -11059,6 +11067,9 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( } case OR_Deleted: { + // FIXME: There are no tests for this diagnostic, and it doesn't seem + // like we ever get here; attempts to trigger this seem to yield a + // generic c'all to deleted function' diagnostic instead. Diag(Kind.getLocation(), diag::err_deduced_class_template_deleted) << TemplateName; NoteDeletedFunction(Best->Function); diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 5b95bae567b7217af0a57f9e6d419acaf6e2ac12..35a51c6c2328dbc7469aea5c3a5ccbe363b75d27 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -9,17 +9,18 @@ // This file implements semantic analysis for C++ lambda expressions. // //===----------------------------------------------------------------------===// -#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/SemaLambda.h" #include "TypeLocBuilder.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Sema/DeclSpec.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" -#include "clang/Sema/SemaLambda.h" #include "clang/Sema/Template.h" #include "llvm/ADT/STLExtras.h" #include @@ -1393,7 +1394,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // CUDA lambdas get implicit host and device attributes. if (getLangOpts().CUDA) - CUDASetLambdaAttrs(Method); + CUDA().SetLambdaAttrs(Method); // OpenMP lambdas might get assumumption attributes. if (LangOpts.OpenMP) @@ -2136,7 +2137,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, CaptureInits.push_back(Init.get()); if (LangOpts.CUDA) - CUDACheckLambdaCapture(CallOperator, From); + CUDA().CheckLambdaCapture(CallOperator, From); } Class->setCaptures(Context, Captures); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 38237ee578079db65a94f5af9614cd1d744f0a6f..d65f52b8efe81f21fae83fab72d9a431e05a9009 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -37,6 +37,7 @@ #include "clang/Sema/TemplateDeduction.h" #include "clang/Sema/TypoCorrection.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/ADT/edit_distance.h" @@ -3341,21 +3342,20 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, Functions.append(Operators.begin(), Operators.end()); } -Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, - CXXSpecialMember SM, - bool ConstArg, - bool VolatileArg, - bool RValueThis, - bool ConstThis, - bool VolatileThis) { +Sema::SpecialMemberOverloadResult +Sema::LookupSpecialMember(CXXRecordDecl *RD, CXXSpecialMemberKind SM, + bool ConstArg, bool VolatileArg, bool RValueThis, + bool ConstThis, bool VolatileThis) { assert(CanDeclareSpecialMemberFunction(RD) && "doing special member lookup into record that isn't fully complete"); RD = RD->getDefinition(); if (RValueThis || ConstThis || VolatileThis) - assert((SM == CXXCopyAssignment || SM == CXXMoveAssignment) && + assert((SM == CXXSpecialMemberKind::CopyAssignment || + SM == CXXSpecialMemberKind::MoveAssignment) && "constructors and destructors always have unqualified lvalue this"); if (ConstArg || VolatileArg) - assert((SM != CXXDefaultConstructor && SM != CXXDestructor) && + assert((SM != CXXSpecialMemberKind::DefaultConstructor && + SM != CXXSpecialMemberKind::Destructor) && "parameter-less special members can't have qualified arguments"); // FIXME: Get the caller to pass in a location for the lookup. @@ -3363,7 +3363,7 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, llvm::FoldingSetNodeID ID; ID.AddPointer(RD); - ID.AddInteger(SM); + ID.AddInteger(llvm::to_underlying(SM)); ID.AddInteger(ConstArg); ID.AddInteger(VolatileArg); ID.AddInteger(RValueThis); @@ -3382,7 +3382,7 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, Result = new (Result) SpecialMemberOverloadResultEntry(ID); SpecialMemberCache.InsertNode(Result, InsertPoint); - if (SM == CXXDestructor) { + if (SM == CXXSpecialMemberKind::Destructor) { if (RD->needsImplicitDestructor()) { runWithSufficientStackSpace(RD->getLocation(), [&] { DeclareImplicitDestructor(RD); @@ -3406,7 +3406,7 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, QualType ArgType = CanTy; ExprValueKind VK = VK_LValue; - if (SM == CXXDefaultConstructor) { + if (SM == CXXSpecialMemberKind::DefaultConstructor) { Name = Context.DeclarationNames.getCXXConstructorName(CanTy); NumArgs = 0; if (RD->needsImplicitDefaultConstructor()) { @@ -3415,7 +3415,8 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, }); } } else { - if (SM == CXXCopyConstructor || SM == CXXMoveConstructor) { + if (SM == CXXSpecialMemberKind::CopyConstructor || + SM == CXXSpecialMemberKind::MoveConstructor) { Name = Context.DeclarationNames.getCXXConstructorName(CanTy); if (RD->needsImplicitCopyConstructor()) { runWithSufficientStackSpace(RD->getLocation(), [&] { @@ -3453,7 +3454,8 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, // Possibly an XValue is actually correct in the case of move, but // there is no semantic difference for class types in this restricted // case. - if (SM == CXXCopyConstructor || SM == CXXCopyAssignment) + if (SM == CXXSpecialMemberKind::CopyConstructor || + SM == CXXSpecialMemberKind::CopyAssignment) VK = VK_LValue; else VK = VK_PRValue; @@ -3461,7 +3463,7 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, OpaqueValueExpr FakeArg(LookupLoc, ArgType, VK); - if (SM != CXXDefaultConstructor) { + if (SM != CXXSpecialMemberKind::DefaultConstructor) { NumArgs = 1; Arg = &FakeArg; } @@ -3487,7 +3489,7 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, // type, rather than because there's some other declared constructor. // Every class has a copy/move constructor, copy/move assignment, and // destructor. - assert(SM == CXXDefaultConstructor && + assert(SM == CXXSpecialMemberKind::DefaultConstructor && "lookup for a constructor or assignment operator was empty"); Result->setMethod(nullptr); Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted); @@ -3505,7 +3507,8 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, DeclAccessPair Cand = DeclAccessPair::make(CandDecl, AS_public); auto CtorInfo = getConstructorInfo(Cand); if (CXXMethodDecl *M = dyn_cast(Cand->getUnderlyingDecl())) { - if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) + if (SM == CXXSpecialMemberKind::CopyAssignment || + SM == CXXSpecialMemberKind::MoveAssignment) AddMethodCandidate(M, Cand, RD, ThisTy, Classification, llvm::ArrayRef(&Arg, NumArgs), OCS, true); else if (CtorInfo) @@ -3517,7 +3520,8 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, /*SuppressUserConversions*/ true); } else if (FunctionTemplateDecl *Tmpl = dyn_cast(Cand->getUnderlyingDecl())) { - if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) + if (SM == CXXSpecialMemberKind::CopyAssignment || + SM == CXXSpecialMemberKind::MoveAssignment) AddMethodTemplateCandidate(Tmpl, Cand, RD, nullptr, ThisTy, Classification, llvm::ArrayRef(&Arg, NumArgs), OCS, true); @@ -3563,8 +3567,8 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, /// Look up the default constructor for the given class. CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) { SpecialMemberOverloadResult Result = - LookupSpecialMember(Class, CXXDefaultConstructor, false, false, false, - false, false); + LookupSpecialMember(Class, CXXSpecialMemberKind::DefaultConstructor, + false, false, false, false, false); return cast_or_null(Result.getMethod()); } @@ -3574,9 +3578,9 @@ CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class, unsigned Quals) { assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) && "non-const, non-volatile qualifiers for copy ctor arg"); - SpecialMemberOverloadResult Result = - LookupSpecialMember(Class, CXXCopyConstructor, Quals & Qualifiers::Const, - Quals & Qualifiers::Volatile, false, false, false); + SpecialMemberOverloadResult Result = LookupSpecialMember( + Class, CXXSpecialMemberKind::CopyConstructor, Quals & Qualifiers::Const, + Quals & Qualifiers::Volatile, false, false, false); return cast_or_null(Result.getMethod()); } @@ -3584,9 +3588,9 @@ CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class, /// Look up the moving constructor for the given class. CXXConstructorDecl *Sema::LookupMovingConstructor(CXXRecordDecl *Class, unsigned Quals) { - SpecialMemberOverloadResult Result = - LookupSpecialMember(Class, CXXMoveConstructor, Quals & Qualifiers::Const, - Quals & Qualifiers::Volatile, false, false, false); + SpecialMemberOverloadResult Result = LookupSpecialMember( + Class, CXXSpecialMemberKind::MoveConstructor, Quals & Qualifiers::Const, + Quals & Qualifiers::Volatile, false, false, false); return cast_or_null(Result.getMethod()); } @@ -3618,11 +3622,10 @@ CXXMethodDecl *Sema::LookupCopyingAssignment(CXXRecordDecl *Class, "non-const, non-volatile qualifiers for copy assignment arg"); assert(!(ThisQuals & ~(Qualifiers::Const | Qualifiers::Volatile)) && "non-const, non-volatile qualifiers for copy assignment this"); - SpecialMemberOverloadResult Result = - LookupSpecialMember(Class, CXXCopyAssignment, Quals & Qualifiers::Const, - Quals & Qualifiers::Volatile, RValueThis, - ThisQuals & Qualifiers::Const, - ThisQuals & Qualifiers::Volatile); + SpecialMemberOverloadResult Result = LookupSpecialMember( + Class, CXXSpecialMemberKind::CopyAssignment, Quals & Qualifiers::Const, + Quals & Qualifiers::Volatile, RValueThis, ThisQuals & Qualifiers::Const, + ThisQuals & Qualifiers::Volatile); return Result.getMethod(); } @@ -3634,11 +3637,10 @@ CXXMethodDecl *Sema::LookupMovingAssignment(CXXRecordDecl *Class, unsigned ThisQuals) { assert(!(ThisQuals & ~(Qualifiers::Const | Qualifiers::Volatile)) && "non-const, non-volatile qualifiers for copy assignment this"); - SpecialMemberOverloadResult Result = - LookupSpecialMember(Class, CXXMoveAssignment, Quals & Qualifiers::Const, - Quals & Qualifiers::Volatile, RValueThis, - ThisQuals & Qualifiers::Const, - ThisQuals & Qualifiers::Volatile); + SpecialMemberOverloadResult Result = LookupSpecialMember( + Class, CXXSpecialMemberKind::MoveAssignment, Quals & Qualifiers::Const, + Quals & Qualifiers::Volatile, RValueThis, ThisQuals & Qualifiers::Const, + ThisQuals & Qualifiers::Volatile); return Result.getMethod(); } @@ -3651,8 +3653,8 @@ CXXMethodDecl *Sema::LookupMovingAssignment(CXXRecordDecl *Class, /// \returns The destructor for this class. CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { return cast_or_null( - LookupSpecialMember(Class, CXXDestructor, false, false, false, false, - false) + LookupSpecialMember(Class, CXXSpecialMemberKind::Destructor, false, false, + false, false, false) .getMethod()); } diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index a6f4453e525d0136ee4b1f3c996d3dec360781dd..1249136c87650bfe0ad22e3eb5a52cc5b163c230 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -55,12 +55,49 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind, default: return false; } + case OpenACCClauseKind::If: + switch (DirectiveKind) { + case OpenACCDirectiveKind::Parallel: + case OpenACCDirectiveKind::Serial: + case OpenACCDirectiveKind::Kernels: + case OpenACCDirectiveKind::Data: + case OpenACCDirectiveKind::EnterData: + case OpenACCDirectiveKind::ExitData: + case OpenACCDirectiveKind::HostData: + case OpenACCDirectiveKind::Init: + case OpenACCDirectiveKind::Shutdown: + case OpenACCDirectiveKind::Set: + case OpenACCDirectiveKind::Update: + case OpenACCDirectiveKind::Wait: + case OpenACCDirectiveKind::ParallelLoop: + case OpenACCDirectiveKind::SerialLoop: + case OpenACCDirectiveKind::KernelsLoop: + return true; + default: + return false; + } default: // Do nothing so we can go to the 'unimplemented' diagnostic instead. return true; } llvm_unreachable("Invalid clause kind"); } + +bool checkAlreadyHasClauseOfKind( + SemaOpenACC &S, ArrayRef ExistingClauses, + SemaOpenACC::OpenACCParsedClause &Clause) { + const auto *Itr = llvm::find_if(ExistingClauses, [&](const OpenACCClause *C) { + return C->getClauseKind() == Clause.getClauseKind(); + }); + if (Itr != ExistingClauses.end()) { + S.Diag(Clause.getBeginLoc(), diag::err_acc_duplicate_clause_disallowed) + << Clause.getDirectiveKind() << Clause.getClauseKind(); + S.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here); + return true; + } + return false; +} + } // namespace SemaOpenACC::SemaOpenACC(Sema &S) : SemaBase(S) {} @@ -97,22 +134,38 @@ SemaOpenACC::ActOnClause(ArrayRef ExistingClauses, // At most one 'default' clause may appear, and it must have a value of // either 'none' or 'present'. // Second half of the sentence is diagnosed during parsing. - auto Itr = llvm::find_if(ExistingClauses, [](const OpenACCClause *C) { - return C->getClauseKind() == OpenACCClauseKind::Default; - }); - - if (Itr != ExistingClauses.end()) { - Diag(Clause.getBeginLoc(), - diag::err_acc_duplicate_clause_disallowed) - << Clause.getDirectiveKind() << Clause.getClauseKind(); - Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here); + if (checkAlreadyHasClauseOfKind(*this, ExistingClauses, Clause)) return nullptr; - } return OpenACCDefaultClause::Create( getASTContext(), Clause.getDefaultClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getEndLoc()); } + + case OpenACCClauseKind::If: { + // Restrictions only properly implemented on 'compute' constructs, and + // 'compute' constructs are the only construct that can do anything with + // this yet, so skip/treat as unimplemented in this case. + if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Parallel && + Clause.getDirectiveKind() != OpenACCDirectiveKind::Serial && + Clause.getDirectiveKind() != OpenACCDirectiveKind::Kernels) + break; + + // There is no prose in the standard that says duplicates aren't allowed, + // but this diagnostic is present in other compilers, as well as makes + // sense. + if (checkAlreadyHasClauseOfKind(*this, ExistingClauses, Clause)) + return nullptr; + + // The parser has ensured that we have a proper condition expr, so there + // isn't really much to do here. + + // TODO OpenACC: When we implement 'self', this clauses causes us to + // 'ignore' the self clause, so we should implement a warning here. + return OpenACCIfClause::Create( + getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(), + Clause.getConditionExpr(), Clause.getEndLoc()); + } default: break; } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 3808af37ff54a8ee65334baea4af9f2d3f828ba3..227ef564ba3e081b9b1fa8abc3504bd84a86f80b 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -31,11 +31,13 @@ #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Overload.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -1548,10 +1550,10 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New, // Don't allow overloading of destructors. (In theory we could, but it // would be a giant change to clang.) if (!isa(New)) { - Sema::CUDAFunctionTarget NewTarget = SemaRef.IdentifyCUDATarget(New), - OldTarget = SemaRef.IdentifyCUDATarget(Old); - if (NewTarget != Sema::CFT_InvalidTarget) { - assert((OldTarget != Sema::CFT_InvalidTarget) && + CUDAFunctionTarget NewTarget = SemaRef.CUDA().IdentifyTarget(New), + OldTarget = SemaRef.CUDA().IdentifyTarget(Old); + if (NewTarget != CUDAFunctionTarget::InvalidTarget) { + assert((OldTarget != CUDAFunctionTarget::InvalidTarget) && "Unexpected invalid target."); // Allow overloading of functions with same signature and different CUDA @@ -7099,7 +7101,7 @@ void Sema::AddOverloadCandidate( // inferred for the member automatically, based on the bases and fields of // the class. if (!(Caller && Caller->isImplicit()) && - !IsAllowedCUDACall(Caller, Function)) { + !CUDA().IsAllowedCall(Caller, Function)) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_target; return; @@ -7617,7 +7619,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // (CUDA B.1): Check for invalid calls between targets. if (getLangOpts().CUDA) - if (!IsAllowedCUDACall(getCurFunctionDecl(/*AllowLambda=*/true), Method)) { + if (!CUDA().IsAllowedCall(getCurFunctionDecl(/*AllowLambda=*/true), + Method)) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_target; return; @@ -10439,7 +10442,7 @@ bool clang::isBetterOverloadCandidate( // If other rules cannot determine which is better, CUDA preference will be // used again to determine which is better. // - // TODO: Currently IdentifyCUDAPreference does not return correct values + // TODO: Currently IdentifyPreference does not return correct values // for functions called in global variable initializers due to missing // correct context about device/host. Therefore we can only enforce this // rule when there is a caller. We should enforce this rule for functions @@ -10451,14 +10454,14 @@ bool clang::isBetterOverloadCandidate( if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function && S.getLangOpts().GPUExcludeWrongSideOverloads) { if (FunctionDecl *Caller = S.getCurFunctionDecl(/*AllowLambda=*/true)) { - bool IsCallerImplicitHD = Sema::isCUDAImplicitHostDeviceFunction(Caller); + bool IsCallerImplicitHD = SemaCUDA::isImplicitHostDeviceFunction(Caller); bool IsCand1ImplicitHD = - Sema::isCUDAImplicitHostDeviceFunction(Cand1.Function); + SemaCUDA::isImplicitHostDeviceFunction(Cand1.Function); bool IsCand2ImplicitHD = - Sema::isCUDAImplicitHostDeviceFunction(Cand2.Function); - auto P1 = S.IdentifyCUDAPreference(Caller, Cand1.Function); - auto P2 = S.IdentifyCUDAPreference(Caller, Cand2.Function); - assert(P1 != Sema::CFP_Never && P2 != Sema::CFP_Never); + SemaCUDA::isImplicitHostDeviceFunction(Cand2.Function); + auto P1 = S.CUDA().IdentifyPreference(Caller, Cand1.Function); + auto P2 = S.CUDA().IdentifyPreference(Caller, Cand2.Function); + assert(P1 != SemaCUDA::CFP_Never && P2 != SemaCUDA::CFP_Never); // The implicit HD function may be a function in a system header which // is forced by pragma. In device compilation, if we prefer HD candidates // over wrong-sided candidates, overloading resolution may change, which @@ -10472,8 +10475,8 @@ bool clang::isBetterOverloadCandidate( auto EmitThreshold = (S.getLangOpts().CUDAIsDevice && IsCallerImplicitHD && (IsCand1ImplicitHD || IsCand2ImplicitHD)) - ? Sema::CFP_Never - : Sema::CFP_WrongSide; + ? SemaCUDA::CFP_Never + : SemaCUDA::CFP_WrongSide; auto Cand1Emittable = P1 > EmitThreshold; auto Cand2Emittable = P2 > EmitThreshold; if (Cand1Emittable && !Cand2Emittable) @@ -10757,8 +10760,8 @@ bool clang::isBetterOverloadCandidate( // to determine which is better. if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function) { FunctionDecl *Caller = S.getCurFunctionDecl(/*AllowLambda=*/true); - return S.IdentifyCUDAPreference(Caller, Cand1.Function) > - S.IdentifyCUDAPreference(Caller, Cand2.Function); + return S.CUDA().IdentifyPreference(Caller, Cand1.Function) > + S.CUDA().IdentifyPreference(Caller, Cand2.Function); } // General member function overloading is handled above, so this only handles @@ -10890,15 +10893,15 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, llvm::any_of(Candidates, [&](OverloadCandidate *Cand) { // Check viable function only. return Cand->Viable && Cand->Function && - S.IdentifyCUDAPreference(Caller, Cand->Function) == - Sema::CFP_SameSide; + S.CUDA().IdentifyPreference(Caller, Cand->Function) == + SemaCUDA::CFP_SameSide; }); if (ContainsSameSideCandidate) { auto IsWrongSideCandidate = [&](OverloadCandidate *Cand) { // Check viable function only to avoid unnecessary data copying/moving. return Cand->Viable && Cand->Function && - S.IdentifyCUDAPreference(Caller, Cand->Function) == - Sema::CFP_WrongSide; + S.CUDA().IdentifyPreference(Caller, Cand->Function) == + SemaCUDA::CFP_WrongSide; }; llvm::erase_if(Candidates, IsWrongSideCandidate); } @@ -11937,8 +11940,8 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { FunctionDecl *Caller = S.getCurFunctionDecl(/*AllowLambda=*/true); FunctionDecl *Callee = Cand->Function; - Sema::CUDAFunctionTarget CallerTarget = S.IdentifyCUDATarget(Caller), - CalleeTarget = S.IdentifyCUDATarget(Callee); + CUDAFunctionTarget CallerTarget = S.CUDA().IdentifyTarget(Caller), + CalleeTarget = S.CUDA().IdentifyTarget(Callee); std::string FnDesc; std::pair FnKindPair = @@ -11948,32 +11951,32 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target) << (unsigned)FnKindPair.first << (unsigned)ocs_non_template << FnDesc /* Ignored */ - << CalleeTarget << CallerTarget; + << llvm::to_underlying(CalleeTarget) << llvm::to_underlying(CallerTarget); // This could be an implicit constructor for which we could not infer the // target due to a collsion. Diagnose that case. CXXMethodDecl *Meth = dyn_cast(Callee); if (Meth != nullptr && Meth->isImplicit()) { CXXRecordDecl *ParentClass = Meth->getParent(); - Sema::CXXSpecialMember CSM; + CXXSpecialMemberKind CSM; switch (FnKindPair.first) { default: return; case oc_implicit_default_constructor: - CSM = Sema::CXXDefaultConstructor; + CSM = CXXSpecialMemberKind::DefaultConstructor; break; case oc_implicit_copy_constructor: - CSM = Sema::CXXCopyConstructor; + CSM = CXXSpecialMemberKind::CopyConstructor; break; case oc_implicit_move_constructor: - CSM = Sema::CXXMoveConstructor; + CSM = CXXSpecialMemberKind::MoveConstructor; break; case oc_implicit_copy_assignment: - CSM = Sema::CXXCopyAssignment; + CSM = CXXSpecialMemberKind::CopyAssignment; break; case oc_implicit_move_assignment: - CSM = Sema::CXXMoveAssignment; + CSM = CXXSpecialMemberKind::MoveAssignment; break; }; @@ -11985,9 +11988,9 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { } } - S.inferCUDATargetForImplicitSpecialMember(ParentClass, CSM, Meth, - /* ConstRHS */ ConstRHS, - /* Diagnose */ true); + S.CUDA().inferTargetForImplicitSpecialMember(ParentClass, CSM, Meth, + /* ConstRHS */ ConstRHS, + /* Diagnose */ true); } } @@ -13059,7 +13062,7 @@ private: if (S.getLangOpts().CUDA) { FunctionDecl *Caller = S.getCurFunctionDecl(/*AllowLambda=*/true); if (!(Caller && Caller->isImplicit()) && - !S.IsAllowedCUDACall(Caller, FunDecl)) + !S.CUDA().IsAllowedCall(Caller, FunDecl)) return false; } if (FunDecl->isMultiVersion()) { @@ -13179,8 +13182,8 @@ private: } void EliminateSuboptimalCudaMatches() { - S.EraseUnwantedCUDAMatches(S.getCurFunctionDecl(/*AllowLambda=*/true), - Matches); + S.CUDA().EraseUnwantedMatches(S.getCurFunctionDecl(/*AllowLambda=*/true), + Matches); } public: @@ -13334,8 +13337,8 @@ Sema::resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &Pair) { // Return positive for better, negative for worse, 0 for equal preference. auto CheckCUDAPreference = [&](FunctionDecl *FD1, FunctionDecl *FD2) { FunctionDecl *Caller = getCurFunctionDecl(/*AllowLambda=*/true); - return static_cast(IdentifyCUDAPreference(Caller, FD1)) - - static_cast(IdentifyCUDAPreference(Caller, FD2)); + return static_cast(CUDA().IdentifyPreference(Caller, FD1)) - + static_cast(CUDA().IdentifyPreference(Caller, FD2)); }; auto CheckMoreConstrained = [&](FunctionDecl *FD1, @@ -14168,15 +14171,13 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, break; case OR_Deleted: { - CandidateSet->NoteCandidates( - PartialDiagnosticAt(Fn->getBeginLoc(), - SemaRef.PDiag(diag::err_ovl_deleted_call) - << ULE->getName() << Fn->getSourceRange()), - SemaRef, OCD_AllCandidates, Args); + FunctionDecl *FDecl = (*Best)->Function; + SemaRef.DiagnoseUseOfDeletedFunction(Fn->getBeginLoc(), + Fn->getSourceRange(), ULE->getName(), + *CandidateSet, FDecl, Args); // We emitted an error for the unavailable/deleted function call but keep // the call in the AST. - FunctionDecl *FDecl = (*Best)->Function; ExprResult Res = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); if (Res.isInvalid()) @@ -14394,9 +14395,16 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, ArrayRef ArgsArray(Args, NumArgs); if (Input->isTypeDependent()) { + ExprValueKind VK = ExprValueKind::VK_PRValue; + // [C++26][expr.unary.op][expr.pre.incr] + // The * operator yields an lvalue of type + // The pre/post increment operators yied an lvalue. + if (Opc == UO_PreDec || Opc == UO_PreInc || Opc == UO_Deref) + VK = VK_LValue; + if (Fns.empty()) - return UnaryOperator::Create(Context, Input, Opc, Context.DependentTy, - VK_PRValue, OK_Ordinary, OpLoc, false, + return UnaryOperator::Create(Context, Input, Opc, Context.DependentTy, VK, + OK_Ordinary, OpLoc, false, CurFPFeatureOverrides()); CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators @@ -14405,7 +14413,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, if (Fn.isInvalid()) return ExprError(); return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), ArgsArray, - Context.DependentTy, VK_PRValue, OpLoc, + Context.DependentTy, VK, OpLoc, CurFPFeatureOverrides()); } @@ -14528,20 +14536,24 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, UnaryOperator::getOpcodeStr(Opc), OpLoc); return ExprError(); - case OR_Deleted: + case OR_Deleted: { // CreateOverloadedUnaryOp fills the first element of ArgsArray with the // object whose method was called. Later in NoteCandidates size of ArgsArray // is passed further and it eventually ends up compared to number of // function candidate parameters which never includes the object parameter, // so slice ArgsArray to make sure apples are compared to apples. + StringLiteral *Msg = Best->Function->getDeletedMessage(); CandidateSet.NoteCandidates( PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_deleted_oper) << UnaryOperator::getOpcodeStr(Opc) + << (Msg != nullptr) + << (Msg ? Msg->getString() : StringRef()) << Input->getSourceRange()), *this, OCD_AllCandidates, ArgsArray.drop_front(), UnaryOperator::getOpcodeStr(Opc), OpLoc); return ExprError(); } + } // Either we found no viable overloaded operator or we matched a // built-in operator. In either case, fall through to trying to @@ -15058,13 +15070,14 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, OpLoc); return ExprError(); - case OR_Deleted: + case OR_Deleted: { if (isImplicitlyDeleted(Best->Function)) { FunctionDecl *DeletedFD = Best->Function; DefaultedFunctionKind DFK = getDefaultedFunctionKind(DeletedFD); if (DFK.isSpecialMember()) { Diag(OpLoc, diag::err_ovl_deleted_special_oper) - << Args[0]->getType() << DFK.asSpecialMember(); + << Args[0]->getType() + << llvm::to_underlying(DFK.asSpecialMember()); } else { assert(DFK.isComparison()); Diag(OpLoc, diag::err_ovl_deleted_comparison) @@ -15076,16 +15089,20 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, NoteDeletedFunction(DeletedFD); return ExprError(); } + + StringLiteral *Msg = Best->Function->getDeletedMessage(); CandidateSet.NoteCandidates( PartialDiagnosticAt( - OpLoc, PDiag(diag::err_ovl_deleted_oper) - << getOperatorSpelling(Best->Function->getDeclName() - .getCXXOverloadedOperator()) - << Args[0]->getSourceRange() - << Args[1]->getSourceRange()), + OpLoc, + PDiag(diag::err_ovl_deleted_oper) + << getOperatorSpelling(Best->Function->getDeclName() + .getCXXOverloadedOperator()) + << (Msg != nullptr) << (Msg ? Msg->getString() : StringRef()) + << Args[0]->getSourceRange() << Args[1]->getSourceRange()), *this, OCD_AllCandidates, Args, BinaryOperator::getOpcodeStr(Opc), OpLoc); return ExprError(); + } } // We matched a built-in operator; build it. @@ -15397,14 +15414,18 @@ ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, } return ExprError(); - case OR_Deleted: + case OR_Deleted: { + StringLiteral *Msg = Best->Function->getDeletedMessage(); CandidateSet.NoteCandidates( - PartialDiagnosticAt(LLoc, PDiag(diag::err_ovl_deleted_oper) - << "[]" << Args[0]->getSourceRange() - << Range), + PartialDiagnosticAt(LLoc, + PDiag(diag::err_ovl_deleted_oper) + << "[]" << (Msg != nullptr) + << (Msg ? Msg->getString() : StringRef()) + << Args[0]->getSourceRange() << Range), *this, OCD_AllCandidates, Args, "[]", LLoc); return ExprError(); } + } // We matched a built-in operator; build it. return CreateBuiltinArraySubscriptExpr(Args[0], LLoc, Args[1], RLoc); @@ -15618,11 +15639,9 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, *this, OCD_AmbiguousCandidates, Args); break; case OR_Deleted: - CandidateSet.NoteCandidates( - PartialDiagnosticAt(UnresExpr->getMemberLoc(), - PDiag(diag::err_ovl_deleted_member_call) - << DeclName << MemExprE->getSourceRange()), - *this, OCD_AllCandidates, Args); + DiagnoseUseOfDeletedFunction( + UnresExpr->getMemberLoc(), MemExprE->getSourceRange(), DeclName, + CandidateSet, Best->Function, Args, /*IsMember=*/true); break; } // Overload resolution fails, try to recover. @@ -15886,15 +15905,21 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, *this, OCD_AmbiguousCandidates, Args); break; - case OR_Deleted: + case OR_Deleted: { + // FIXME: Is this diagnostic here really necessary? It seems that + // 1. we don't have any tests for this diagnostic, and + // 2. we already issue err_deleted_function_use for this later on anyway. + StringLiteral *Msg = Best->Function->getDeletedMessage(); CandidateSet.NoteCandidates( PartialDiagnosticAt(Object.get()->getBeginLoc(), PDiag(diag::err_ovl_deleted_object_call) - << Object.get()->getType() + << Object.get()->getType() << (Msg != nullptr) + << (Msg ? Msg->getString() : StringRef()) << Object.get()->getSourceRange()), *this, OCD_AllCandidates, Args); break; } + } if (Best == CandidateSet.end()) return true; @@ -16093,13 +16118,17 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, *this, OCD_AmbiguousCandidates, Base); return ExprError(); - case OR_Deleted: + case OR_Deleted: { + StringLiteral *Msg = Best->Function->getDeletedMessage(); CandidateSet.NoteCandidates( PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_deleted_oper) - << "->" << Base->getSourceRange()), + << "->" << (Msg != nullptr) + << (Msg ? Msg->getString() : StringRef()) + << Base->getSourceRange()), *this, OCD_AllCandidates, Base); return ExprError(); } + } CheckMemberOperatorAccess(OpLoc, Base, nullptr, Best->FoundDecl); @@ -16513,3 +16542,17 @@ bool clang::shouldEnforceArgLimit(bool PartialOverloading, return false; return true; } + +void Sema::DiagnoseUseOfDeletedFunction(SourceLocation Loc, SourceRange Range, + DeclarationName Name, + OverloadCandidateSet &CandidateSet, + FunctionDecl *Fn, MultiExprArg Args, + bool IsMember) { + StringLiteral *Msg = Fn->getDeletedMessage(); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(Loc, PDiag(diag::err_ovl_deleted_call) + << IsMember << Name << (Msg != nullptr) + << (Msg ? Msg->getString() : StringRef()) + << Range), + *this, OCD_AllCandidates, Args); +} diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index e53c76e65b03d240355b4e27f0691341b988a22d..d28c24cfdfd33c5091be1b56a7c4dae6136e94f9 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -33,10 +33,12 @@ #include "clang/Sema/Ownership.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -4573,8 +4575,8 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, // Exceptions aren't allowed in CUDA device code. if (getLangOpts().CUDA) - CUDADiagIfDeviceCode(TryLoc, diag::err_cuda_device_exceptions) - << "try" << CurrentCUDATarget(); + CUDA().DiagIfDeviceCode(TryLoc, diag::err_cuda_device_exceptions) + << "try" << llvm::to_underlying(CUDA().CurrentTarget()); if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope()) Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try"; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index e0f5e53dc2481e5ba00fb5024ff8e6b75c4709b4..95171359f0ab174ddf9be131baa65a3acc6cef84 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -33,6 +33,7 @@ #include "clang/Sema/Overload.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" @@ -10155,9 +10156,9 @@ bool Sema::CheckFunctionTemplateSpecialization( // take target attributes into account, we reject candidates // here that have a different target. if (LangOpts.CUDA && - IdentifyCUDATarget(Specialization, - /* IgnoreImplicitHDAttr = */ true) != - IdentifyCUDATarget(FD, /* IgnoreImplicitHDAttr = */ true)) { + CUDA().IdentifyTarget(Specialization, + /* IgnoreImplicitHDAttr = */ true) != + CUDA().IdentifyTarget(FD, /* IgnoreImplicitHDAttr = */ true)) { FailedCandidates.addCandidate().set( I.getPair(), FunTmpl->getTemplatedDecl(), MakeDeductionFailureInfo( @@ -10328,7 +10329,7 @@ bool Sema::CheckFunctionTemplateSpecialization( // virtue e.g. of being constexpr, and it passes these implicit // attributes on to its specializations.) if (LangOpts.CUDA) - inheritCUDATargetAttrs(FD, *Specialization->getPrimaryTemplate()); + CUDA().inheritTargetAttrs(FD, *Specialization->getPrimaryTemplate()); // The "previous declaration" for this function template specialization is // the prior function template specialization. @@ -11364,9 +11365,9 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // target attributes into account, we reject candidates here that // have a different target. if (LangOpts.CUDA && - IdentifyCUDATarget(Specialization, - /* IgnoreImplicitHDAttr = */ true) != - IdentifyCUDATarget(D.getDeclSpec().getAttributes())) { + CUDA().IdentifyTarget(Specialization, + /* IgnoreImplicitHDAttr = */ true) != + CUDA().IdentifyTarget(D.getDeclSpec().getAttributes())) { FailedCandidates.addCandidate().set( P.getPair(), FunTmpl->getTemplatedDecl(), MakeDeductionFailureInfo( diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index a265fd1c46a63e937ec4144e9c4acdddd263f3ff..7cd428de0bb32d2a29d36e1bf60b638b0bd6b315 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -36,6 +36,7 @@ #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" #include "clang/Sema/TemplateInstCallback.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TimeProfiler.h" @@ -1142,7 +1143,8 @@ void Sema::PrintInstantiationStack() { case CodeSynthesisContext::DeclaringSpecialMember: Diags.Report(Active->PointOfInstantiation, diag::note_in_declaration_of_implicit_special_member) - << cast(Active->Entity) << Active->SpecialMember; + << cast(Active->Entity) + << llvm::to_underlying(Active->SpecialMember); break; case CodeSynthesisContext::DeclaringImplicitEqualityComparison: @@ -1160,7 +1162,8 @@ void Sema::PrintInstantiationStack() { auto *MD = cast(FD); Diags.Report(Active->PointOfInstantiation, diag::note_member_synthesized_at) - << MD->isExplicitlyDefaulted() << DFK.asSpecialMember() + << MD->isExplicitlyDefaulted() + << llvm::to_underlying(DFK.asSpecialMember()) << Context.getTagDeclType(MD->getParent()); } else if (DFK.isComparison()) { QualType RecordType = FD->getParamDecl(0) diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 707446e132094f511c2e245770a5142aa63b4d6e..c45a8d1408fff3454294476e115d642b5fe5a73e 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -26,6 +26,7 @@ #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateInstCallback.h" @@ -2438,7 +2439,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( return nullptr; } if (D->isDeleted()) - SemaRef.SetDeclDeleted(Function, D->getLocation()); + SemaRef.SetDeclDeleted(Function, D->getLocation(), D->getDeletedMessage()); NamedDecl *PrincipalDecl = (TemplateParams ? cast(FunctionTemplate) : Function); @@ -2814,7 +2815,8 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( return nullptr; } if (D->isDeletedAsWritten()) - SemaRef.SetDeclDeleted(Method, Method->getLocation()); + SemaRef.SetDeclDeleted(Method, Method->getLocation(), + D->getDeletedMessage()); // If this is an explicit specialization, mark the implicitly-instantiated // template specialization as being an explicit specialization too. @@ -4866,7 +4868,7 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, bool TemplateDeclInstantiator::SubstDefaultedFunction(FunctionDecl *New, FunctionDecl *Tmpl) { // Transfer across any unqualified lookups. - if (auto *DFI = Tmpl->getDefaultedFunctionInfo()) { + if (auto *DFI = Tmpl->getDefalutedOrDeletedInfo()) { SmallVector Lookups; Lookups.reserve(DFI->getUnqualifiedLookups().size()); bool AnyChanged = false; @@ -4881,8 +4883,8 @@ bool TemplateDeclInstantiator::SubstDefaultedFunction(FunctionDecl *New, // It's unlikely that substitution will change any declarations. Don't // store an unnecessary copy in that case. - New->setDefaultedFunctionInfo( - AnyChanged ? FunctionDecl::DefaultedFunctionInfo::Create( + New->setDefaultedOrDeletedInfo( + AnyChanged ? FunctionDecl::DefaultedOrDeletedFunctionInfo::Create( SemaRef.Context, Lookups) : DFI); } @@ -5095,14 +5097,6 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, EnterExpressionEvaluationContext EvalContext( *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); - Qualifiers ThisTypeQuals; - CXXRecordDecl *ThisContext = nullptr; - if (CXXMethodDecl *Method = dyn_cast(Function)) { - ThisContext = Method->getParent(); - ThisTypeQuals = Method->getMethodQualifiers(); - } - CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals); - // Introduce a new scope where local variable instantiations will be // recorded, unless we're actually a member function within a local // class, in which case we need to merge our results with the parent @@ -5123,10 +5117,10 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, assert(PatternDecl->isDefaulted() && "Special member needs to be defaulted"); auto PatternSM = getDefaultedFunctionKind(PatternDecl).asSpecialMember(); - if (!(PatternSM == Sema::CXXCopyConstructor || - PatternSM == Sema::CXXCopyAssignment || - PatternSM == Sema::CXXMoveConstructor || - PatternSM == Sema::CXXMoveAssignment)) + if (!(PatternSM == CXXSpecialMemberKind::CopyConstructor || + PatternSM == CXXSpecialMemberKind::CopyAssignment || + PatternSM == CXXSpecialMemberKind::MoveConstructor || + PatternSM == CXXSpecialMemberKind::MoveAssignment)) return; auto *NewRec = dyn_cast(Function->getDeclContext()); @@ -5489,7 +5483,6 @@ void Sema::InstantiateVariableInitializer( *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var); keepInLifetimeExtendingContext(); - keepInMaterializeTemporaryObjectContext(); // Instantiate the initializer. ExprResult Init; @@ -5537,7 +5530,7 @@ void Sema::InstantiateVariableInitializer( } if (getLangOpts().CUDA) - checkAllowedCUDAInitializer(Var); + CUDA().checkAllowedInitializer(Var); } /// Instantiate the definition of the given variable from its diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 8762744396f4dd3b8938f01020cdaa2214f2d52a..404c4e8e31b558228acd2a39cdef5b93a460bf0b 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -33,10 +33,12 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateInstCallback.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -376,11 +378,10 @@ enum TypeAttrLocation { static void processTypeAttrs(TypeProcessingState &state, QualType &type, TypeAttrLocation TAL, const ParsedAttributesView &attrs, - Sema::CUDAFunctionTarget CFT = Sema::CFT_HostDevice); + CUDAFunctionTarget CFT = CUDAFunctionTarget::HostDevice); static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, - QualType &type, - Sema::CUDAFunctionTarget CFT); + QualType &type, CUDAFunctionTarget CFT); static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &state, ParsedAttr &attr, QualType &type); @@ -627,7 +628,7 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state, static bool distributeFunctionTypeAttrToInnermost( TypeProcessingState &state, ParsedAttr &attr, ParsedAttributesView &attrList, QualType &declSpecType, - Sema::CUDAFunctionTarget CFT) { + CUDAFunctionTarget CFT) { Declarator &declarator = state.getDeclarator(); // Put it on the innermost function chunk, if there is one. @@ -644,10 +645,10 @@ static bool distributeFunctionTypeAttrToInnermost( /// A function type attribute was written in the decl spec. Try to /// apply it somewhere. -static void -distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state, - ParsedAttr &attr, QualType &declSpecType, - Sema::CUDAFunctionTarget CFT) { +static void distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state, + ParsedAttr &attr, + QualType &declSpecType, + CUDAFunctionTarget CFT) { state.saveDeclSpecAttrs(); // Try to distribute to the innermost. @@ -664,9 +665,10 @@ distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state, /// Try to apply it somewhere. /// `Attrs` is the attribute list containing the declaration (either of the /// declarator or the declaration). -static void distributeFunctionTypeAttrFromDeclarator( - TypeProcessingState &state, ParsedAttr &attr, QualType &declSpecType, - Sema::CUDAFunctionTarget CFT) { +static void distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state, + ParsedAttr &attr, + QualType &declSpecType, + CUDAFunctionTarget CFT) { Declarator &declarator = state.getDeclarator(); // Try to distribute to the innermost. @@ -694,7 +696,7 @@ static void distributeFunctionTypeAttrFromDeclarator( /// declarator or the declaration). static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, QualType &declSpecType, - Sema::CUDAFunctionTarget CFT) { + CUDAFunctionTarget CFT) { // The called functions in this loop actually remove things from the current // list, so iterating over the existing list isn't possible. Instead, make a // non-owning copy and iterate over that. @@ -2734,7 +2736,7 @@ QualType Sema::BuildArrayType(QualType T, ArraySizeModifier ASM, bool IsCUDADevice = (getLangOpts().CUDA && getLangOpts().CUDAIsDevice); targetDiag(Loc, IsCUDADevice ? diag::err_cuda_vla : diag::err_vla_unsupported) - << (IsCUDADevice ? CurrentCUDATarget() : 0); + << (IsCUDADevice ? llvm::to_underlying(CUDA().CurrentTarget()) : 0); } else if (sema::FunctionScopeInfo *FSI = getCurFunction()) { // VLAs are supported on this target, but we may need to do delayed // checking that the VLA is not being used within a coroutine. @@ -3617,7 +3619,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // D.getDeclarationAttributes()) because those are always C++11 attributes, // and those don't get distributed. distributeTypeAttrsFromDeclarator( - state, T, SemaRef.IdentifyCUDATarget(D.getAttributes())); + state, T, SemaRef.CUDA().IdentifyTarget(D.getAttributes())); // Find the deduced type in this type. Look in the trailing return type if we // have one, otherwise in the DeclSpec type. @@ -4138,7 +4140,7 @@ static CallingConv getCCForDeclaratorChunk( // handleFunctionTypeAttr. CallingConv CC; if (!S.CheckCallingConvAttr(AL, CC, /*FunctionDecl=*/nullptr, - S.IdentifyCUDATarget(D.getAttributes())) && + S.CUDA().IdentifyTarget(D.getAttributes())) && (!FTI.isVariadic || supportsVariadicCall(CC))) { return CC; } @@ -5824,7 +5826,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // See if there are any attributes on this declarator chunk. processTypeAttrs(state, T, TAL_DeclChunk, DeclType.getAttrs(), - S.IdentifyCUDATarget(D.getAttributes())); + S.CUDA().IdentifyTarget(D.getAttributes())); if (DeclType.Kind != DeclaratorChunk::Paren) { if (ExpectNoDerefChunk && !IsNoDerefableChunk(DeclType)) @@ -8028,8 +8030,7 @@ static bool handleArmStateAttribute(Sema &S, /// Process an individual function attribute. Returns true to /// indicate that the attribute was handled, false if it wasn't. static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, - QualType &type, - Sema::CUDAFunctionTarget CFT) { + QualType &type, CUDAFunctionTarget CFT) { Sema &S = state.getSema(); FunctionTypeUnwrapper unwrapped(S, type); @@ -8863,7 +8864,7 @@ static void HandleHLSLParamModifierAttr(QualType &CurType, static void processTypeAttrs(TypeProcessingState &state, QualType &type, TypeAttrLocation TAL, const ParsedAttributesView &attrs, - Sema::CUDAFunctionTarget CFT) { + CUDAFunctionTarget CFT) { state.setParsedNoDeref(false); if (attrs.empty()) @@ -9738,7 +9739,8 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, : diag::note_non_literal_nontrivial_dtor) << RD; if (!Dtor->isUserProvided()) - SpecialMemberIsTrivial(Dtor, CXXDestructor, TAH_IgnoreTrivialABI, + SpecialMemberIsTrivial(Dtor, CXXSpecialMemberKind::Destructor, + TAH_IgnoreTrivialABI, /*Diagnose*/ true); } } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 284c9173e68ed57c43d6015e4c17131de7a245c9..8c96134af7c8f0abd146dfaa681530191169a778 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -795,9 +795,6 @@ public: ParenExpr *PE, DependentScopeDeclRefExpr *DRE, bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI); - ExprResult TransformUnresolvedLookupExpr(UnresolvedLookupExpr *E, - bool IsAddressOfOperand); - StmtResult TransformOMPExecutableDirective(OMPExecutableDirective *S); // FIXME: We use LLVM_ATTRIBUTE_NOINLINE because inlining causes a ridiculous @@ -3312,13 +3309,12 @@ public: /// Build a new C++ "this" expression. /// - /// By default, performs semantic analysis to build a new "this" expression. - /// Subclasses may override this routine to provide different behavior. + /// By default, builds a new "this" expression without performing any + /// semantic analysis. Subclasses may override this routine to provide + /// different behavior. ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc, QualType ThisType, bool isImplicit) { - if (getSema().CheckCXXThisType(ThisLoc, ThisType)) - return ExprError(); return getSema().BuildCXXThisExpr(ThisLoc, ThisType, isImplicit); } @@ -4181,7 +4177,6 @@ ExprResult TreeTransform::TransformInitializer(Expr *Init, getSema(), EnterExpressionEvaluationContext::InitList, Construct->isListInitialization()); - getSema().keepInLifetimeExtendingContext(); getSema().keepInLifetimeExtendingContext(); SmallVector NewArgs; bool ArgChanged = false; @@ -8756,10 +8751,6 @@ TreeTransform::TransformCXXForRangeStmt(CXXForRangeStmt *S) { if (getSema().getLangOpts().CPlusPlus23) { auto &LastRecord = getSema().ExprEvalContexts.back(); LastRecord.InLifetimeExtendingContext = true; - - // Materialize non-`cv void` prvalue temporaries in discarded - // expressions. These materialized temporaries may be lifetime-extented. - LastRecord.InMaterializeTemporaryObjectContext = true; } StmtResult Init = S->getInit() ? getDerived().TransformStmt(S->getInit()) : StmtResult(); @@ -11103,6 +11094,20 @@ OpenACCClause *TreeTransform::TransformOpenACCClause( ParsedClause.setDefaultDetails( cast(OldClause)->getDefaultClauseKind()); break; + case OpenACCClauseKind::If: { + Expr *Cond = const_cast( + cast(OldClause)->getConditionExpr()); + assert(Cond && "If constructed with invalid Condition"); + Sema::ConditionResult Res = + TransformCondition(Cond->getExprLoc(), /*Var=*/nullptr, Cond, + Sema::ConditionKind::Boolean); + + if (Res.isInvalid() || !Res.get().second) + return nullptr; + + ParsedClause.setConditionDetails(Res.get().second); + break; + } default: assert(false && "Unhandled OpenACC clause in TreeTransform"); return nullptr; @@ -11355,11 +11360,7 @@ template ExprResult TreeTransform::TransformAddressOfOperand(Expr *E) { if (DependentScopeDeclRefExpr *DRE = dyn_cast(E)) - return getDerived().TransformDependentScopeDeclRefExpr( - DRE, /*IsAddressOfOperand=*/true, nullptr); - else if (UnresolvedLookupExpr *ULE = dyn_cast(E)) - return getDerived().TransformUnresolvedLookupExpr( - ULE, /*IsAddressOfOperand=*/true); + return getDerived().TransformDependentScopeDeclRefExpr(DRE, true, nullptr); else return getDerived().TransformExpr(E); } @@ -13065,16 +13066,10 @@ bool TreeTransform::TransformOverloadExprDecls(OverloadExpr *Old, return false; } -template -ExprResult TreeTransform::TransformUnresolvedLookupExpr( - UnresolvedLookupExpr *Old) { - return TransformUnresolvedLookupExpr(Old, /*IsAddressOfOperand=*/false); -} - -template +template ExprResult -TreeTransform::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old, - bool IsAddressOfOperand) { +TreeTransform::TransformUnresolvedLookupExpr( + UnresolvedLookupExpr *Old) { LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(), Sema::LookupOrdinaryName); @@ -13106,8 +13101,26 @@ TreeTransform::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old, R.setNamingClass(NamingClass); } - // Rebuild the template arguments, if any. SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc(); + + // If we have neither explicit template arguments, nor the template keyword, + // it's a normal declaration name or member reference. + if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) { + NamedDecl *D = R.getAsSingle(); + // In a C++11 unevaluated context, an UnresolvedLookupExpr might refer to an + // instance member. In other contexts, BuildPossibleImplicitMemberExpr will + // give a good diagnostic. + if (D && D->isCXXInstanceMember()) { + return SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, + /*TemplateArgs=*/nullptr, + /*Scope=*/nullptr); + } + + return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL()); + } + + // If we have template arguments, rebuild them, then rebuild the + // templateid expression. TemplateArgumentListInfo TransArgs(Old->getLAngleLoc(), Old->getRAngleLoc()); if (Old->hasExplicitTemplateArgs() && getDerived().TransformTemplateArguments(Old->getTemplateArgs(), @@ -13117,23 +13130,6 @@ TreeTransform::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old, return ExprError(); } - // An UnresolvedLookupExpr can refer to a class member. This occurs e.g. when - // a non-static data member is named in an unevaluated operand, or when - // a member is named in a dependent class scope function template explicit - // specialization that is neither declared static nor with an explicit object - // parameter. - if (SemaRef.isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand)) - return SemaRef.BuildPossibleImplicitMemberExpr( - SS, TemplateKWLoc, R, - Old->hasExplicitTemplateArgs() ? &TransArgs : nullptr, - /*S=*/nullptr); - - // If we have neither explicit template arguments, nor the template keyword, - // it's a normal declaration name or member reference. - if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) - return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL()); - - // If we have template arguments, then rebuild the template-id expression. return getDerived().RebuildTemplateIdExpr(SS, TemplateKWLoc, R, Old->requiresADL(), &TransArgs); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 4f6987f92fc82ef38e5667fcb9e47c596c3c7297..8c4b460970ad2b335c1411641624c71d6a3dff08 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -78,6 +78,7 @@ #include "clang/Sema/ObjCMethodList.h" #include "clang/Sema/Scope.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/Weak.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTDeserializationListener.h" @@ -3795,6 +3796,29 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, } break; + case DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD: { + if (Record.size() % 3 != 0) + return llvm::createStringError( + std::errc::illegal_byte_sequence, + "invalid DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD block in AST " + "file"); + for (unsigned I = 0, N = Record.size(); I != N; I += 3) { + GlobalDeclID ID = getGlobalDeclID(F, Record[I]); + + uint64_t BaseOffset = F.DeclsBlockStartOffset; + assert(BaseOffset && "Invalid DeclsBlockStartOffset for module file!"); + uint64_t LexicalOffset = Record[I + 1] ? BaseOffset + Record[I + 1] : 0; + uint64_t VisibleOffset = Record[I + 2] ? BaseOffset + Record[I + 2] : 0; + + DelayedNamespaceOffsetMap[ID] = {LexicalOffset, VisibleOffset}; + + assert(!GetExistingDecl(ID) && + "We shouldn't load the namespace in the front of delayed " + "namespace lexical and visible block"); + } + break; + } + case OBJC_CATEGORIES_MAP: if (F.LocalNumObjCCategoriesInMap != 0) return llvm::createStringError( @@ -3972,7 +3996,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, if (Record.size() != 1) return llvm::createStringError(std::errc::illegal_byte_sequence, "invalid cuda pragma options record"); - ForceCUDAHostDeviceDepth = Record[0]; + ForceHostDeviceDepth = Record[0]; break; case ALIGN_PACK_PRAGMA_OPTIONS: { @@ -8251,7 +8275,7 @@ void ASTReader::UpdateSema() { PragmaMSPointersToMembersState, PointersToMembersPragmaLocation); } - SemaObj->ForceCUDAHostDeviceDepth = ForceCUDAHostDeviceDepth; + SemaObj->CUDA().ForceHostDeviceDepth = ForceHostDeviceDepth; if (PragmaAlignPackCurrentValue) { // The bottom of the stack might have a default value. It must be adjusted @@ -11764,6 +11788,12 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { return OpenACCDefaultClause::Create(getContext(), DCK, BeginLoc, LParenLoc, EndLoc); } + case OpenACCClauseKind::If: { + SourceLocation LParenLoc = readSourceLocation(); + Expr *CondExpr = readSubExpr(); + return OpenACCIfClause::Create(getContext(), BeginLoc, LParenLoc, CondExpr, + EndLoc); + } case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: case OpenACCClauseKind::Seq: @@ -11772,7 +11802,6 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { case OpenACCClauseKind::Worker: case OpenACCClauseKind::Vector: case OpenACCClauseKind::NoHost: - case OpenACCClauseKind::If: case OpenACCClauseKind::Self: case OpenACCClauseKind::Copy: case OpenACCClauseKind::UseDevice: diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 5b7b9f19a106c3b2d01a08683767d44f7bcaef64..e4b6a75c118ba3345f2485f68bae91df222d333b 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1103,16 +1103,26 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->setHasODRHash(true); } - if (FD->isDefaulted()) { - if (unsigned NumLookups = Record.readInt()) { + if (FD->isDefaulted() || FD->isDeletedAsWritten()) { + // If 'Info' is nonzero, we need to read an DefaultedOrDeletedInfo; if, + // additionally, the second bit is also set, we also need to read + // a DeletedMessage for the DefaultedOrDeletedInfo. + if (auto Info = Record.readInt()) { + bool HasMessage = Info & 2; + StringLiteral *DeletedMessage = + HasMessage ? cast(Record.readExpr()) : nullptr; + + unsigned NumLookups = Record.readInt(); SmallVector Lookups; for (unsigned I = 0; I != NumLookups; ++I) { NamedDecl *ND = Record.readDeclAs(); AccessSpecifier AS = (AccessSpecifier)Record.readInt(); Lookups.push_back(DeclAccessPair::make(ND, AS)); } - FD->setDefaultedFunctionInfo(FunctionDecl::DefaultedFunctionInfo::Create( - Reader.getContext(), Lookups)); + + FD->setDefaultedOrDeletedInfo( + FunctionDecl::DefaultedOrDeletedFunctionInfo::Create( + Reader.getContext(), Lookups, DeletedMessage)); } } @@ -4125,6 +4135,15 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { // offsets for its tables of lexical and visible declarations. if (auto *DC = dyn_cast(D)) { std::pair Offsets = Reader.VisitDeclContext(DC); + + // Get the lexical and visible block for the delayed namespace. + // It is sufficient to judge if ID is in DelayedNamespaceOffsetMap. + // But it may be more efficient to filter the other cases. + if (!Offsets.first && !Offsets.second && isa(D)) + if (auto Iter = DelayedNamespaceOffsetMap.find(ID); + Iter != DelayedNamespaceOffsetMap.end()) + Offsets = Iter->second; + if (Offsets.first && ReadLexicalDeclContextStorage(*Loc.F, DeclsCursor, Offsets.first, DC)) return nullptr; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index ffc53292e39124bf631827e0313545b551f26705..85b7fd5535a1bf8e1729168d5b0d0a96ad4e5e76 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -65,6 +65,7 @@ #include "clang/Sema/IdentifierResolver.h" #include "clang/Sema/ObjCMethodList.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/Weak.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTReader.h" @@ -185,8 +186,7 @@ GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) { if (!File) continue; - const HeaderFileInfo *HFI = - HS.getExistingFileInfo(*File, /*WantExternal*/ false); + const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File); if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader)) continue; @@ -870,6 +870,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(WEAK_UNDECLARED_IDENTIFIERS); RECORD(PENDING_IMPLICIT_INSTANTIATIONS); RECORD(UPDATE_VISIBLE); + RECORD(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD); RECORD(DECL_UPDATE_OFFSETS); RECORD(DECL_UPDATES); RECORD(CUDA_SPECIAL_DECL_REFS); @@ -2052,14 +2053,12 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { if (!File) continue; - // Get the file info. This will load info from the external source if - // necessary. Skip emitting this file if we have no information on it - // as a header file (in which case HFI will be null) or if it hasn't + // Get the file info. Skip emitting this file if we have no information on + // it as a header file (in which case HFI will be null) or if it hasn't // changed since it was loaded. Also skip it if it's for a modular header // from a different module; in that case, we rely on the module(s) // containing the header to provide this information. - const HeaderFileInfo *HFI = - HS.getExistingFileInfo(*File, /*WantExternal*/!Chain); + const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File); if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader)) continue; @@ -3029,10 +3028,12 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Stream.EmitRecordWithBlob(ConfigMacroAbbrev, Record, CM); } - // Emit the initializers, if any. + // Emit the reachable initializers. + // The initializer may only be unreachable in reduced BMI. RecordData Inits; for (Decl *D : Context->getModuleInitializers(Mod)) - Inits.push_back(GetDeclRef(D)); + if (wasDeclEmitted(D)) + Inits.push_back(GetDeclRef(D)); if (!Inits.empty()) Stream.EmitRecord(SUBMODULE_INITIALIZERS, Inits); @@ -3211,6 +3212,9 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, uint64_t Offset = Stream.GetCurrentBitNo(); SmallVector KindDeclPairs; for (const auto *D : DC->decls()) { + if (DoneWritingDeclsAndTypes && !wasDeclEmitted(D)) + continue; + KindDeclPairs.push_back(D->getKind()); KindDeclPairs.push_back(GetDeclRef(D)); } @@ -3865,8 +3869,14 @@ public: data_type getData(const Coll &Decls) { unsigned Start = DeclIDs.size(); for (NamedDecl *D : Decls) { - DeclIDs.push_back( - Writer.GetDeclRef(getDeclForLocalLookup(Writer.getLangOpts(), D))); + NamedDecl *DeclForLocalLookup = + getDeclForLocalLookup(Writer.getLangOpts(), D); + + if (Writer.getDoneWritingDeclsAndTypes() && + !Writer.wasDeclEmitted(DeclForLocalLookup)) + continue; + + DeclIDs.push_back(Writer.GetDeclRef(DeclForLocalLookup)); } return std::make_pair(Start, DeclIDs.size()); } @@ -3975,11 +3985,20 @@ bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result, DC->hasNeedToReconcileExternalVisibleStorage(); } -bool ASTWriter::isLookupResultEntirelyExternal(StoredDeclsList &Result, - DeclContext *DC) { - for (auto *D : Result.getLookupResult()) - if (!getDeclForLocalLookup(getLangOpts(), D)->isFromASTFile()) - return false; +bool ASTWriter::isLookupResultEntirelyExternalOrUnreachable( + StoredDeclsList &Result, DeclContext *DC) { + for (auto *D : Result.getLookupResult()) { + auto *LocalD = getDeclForLocalLookup(getLangOpts(), D); + if (LocalD->isFromASTFile()) + continue; + + // We can only be sure whether the local declaration is reachable + // after we done writing the declarations and types. + if (DoneWritingDeclsAndTypes && !wasDeclEmitted(LocalD)) + continue; + + return false; + } return true; } @@ -4017,8 +4036,17 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC, // don't need to write an entry for the name at all. If we can't // write out a lookup set without performing more deserialization, // just skip this entry. - if (isLookupResultExternal(Result, DC) && - isLookupResultEntirelyExternal(Result, DC)) + // + // Also in reduced BMI, we'd like to avoid writing unreachable + // declarations in GMF, so we need to avoid writing declarations + // that entirely external or unreachable. + // + // FIMXE: It looks sufficient to test + // isLookupResultEntirelyExternalOrUnreachable here. But due to bug we have + // to test isLookupResultExternal here. See + // https://github.com/llvm/llvm-project/issues/61065 for details. + if ((GeneratingReducedBMI || isLookupResultExternal(Result, DC)) && + isLookupResultEntirelyExternalOrUnreachable(Result, DC)) continue; // We also skip empty results. If any of the results could be external and @@ -4209,9 +4237,15 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, continue; } - for (NamedDecl *ND : Result) - if (!ND->isFromASTFile()) - GetDeclRef(ND); + for (NamedDecl *ND : Result) { + if (ND->isFromASTFile()) + continue; + + if (DoneWritingDeclsAndTypes && !wasDeclEmitted(ND)) + continue; + + GetDeclRef(ND); + } } return 0; @@ -4302,8 +4336,8 @@ void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) { Stream.EmitRecord(OPENCL_EXTENSIONS, Record); } void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) { - if (SemaRef.ForceCUDAHostDeviceDepth > 0) { - RecordData::value_type Record[] = {SemaRef.ForceCUDAHostDeviceDepth}; + if (SemaRef.CUDA().ForceHostDeviceDepth > 0) { + RecordData::value_type Record[] = {SemaRef.CUDA().ForceHostDeviceDepth}; Stream.EmitRecord(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH, Record); } } @@ -4979,9 +5013,18 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); // Force all top level declarations to be emitted. - for (const auto *D : TU->noload_decls()) - if (!D->isFromASTFile()) - GetDeclRef(D); + // + // We start emitting top level declarations from the module purview to + // implement the eliding unreachable declaration feature. + for (const auto *D : TU->noload_decls()) { + if (D->isFromASTFile()) + continue; + + if (GeneratingReducedBMI && D->isFromExplicitGlobalModule()) + continue; + + GetDeclRef(D); + } // If the translation unit has an anonymous namespace, and we don't already // have an update block for it, write it as an update block. @@ -5291,24 +5334,59 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) { WriteDecl(Context, DOT.getDecl()); } } while (!DeclUpdates.empty()); - Stream.ExitBlock(); DoneWritingDeclsAndTypes = true; + // DelayedNamespace is only meaningful in reduced BMI. + // See the comments of DelayedNamespace for details. + assert(DelayedNamespace.empty() || GeneratingReducedBMI); + RecordData DelayedNamespaceRecord; + for (NamespaceDecl *NS : DelayedNamespace) { + uint64_t LexicalOffset = WriteDeclContextLexicalBlock(Context, NS); + uint64_t VisibleOffset = WriteDeclContextVisibleBlock(Context, NS); + + // Write the offset relative to current block. + if (LexicalOffset) + LexicalOffset -= DeclTypesBlockStartOffset; + + if (VisibleOffset) + VisibleOffset -= DeclTypesBlockStartOffset; + + DelayedNamespaceRecord.push_back(getDeclID(NS)); + DelayedNamespaceRecord.push_back(LexicalOffset); + DelayedNamespaceRecord.push_back(VisibleOffset); + } + + // The process of writing lexical and visible block for delayed namespace + // shouldn't introduce any new decls, types or update to emit. + assert(DeclTypesToEmit.empty()); + assert(DeclUpdates.empty()); + + Stream.ExitBlock(); + // These things can only be done once we've written out decls and types. WriteTypeDeclOffsets(); if (!DeclUpdatesOffsetsRecord.empty()) Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord); + if (!DelayedNamespaceRecord.empty()) + Stream.EmitRecord(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD, + DelayedNamespaceRecord); + const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); // Create a lexical update block containing all of the declarations in the // translation unit that do not come from other AST files. SmallVector NewGlobalKindDeclPairs; for (const auto *D : TU->noload_decls()) { - if (!D->isFromASTFile()) { - NewGlobalKindDeclPairs.push_back(D->getKind()); - NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); - } + if (D->isFromASTFile()) + continue; + + // In reduced BMI, skip unreached declarations. + if (!wasDeclEmitted(D)) + continue; + + NewGlobalKindDeclPairs.push_back(D->getKind()); + NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); } auto Abv = std::make_shared(); @@ -5817,6 +5895,21 @@ DeclID ASTWriter::getDeclID(const Decl *D) { return DeclIDs[D]; } +bool ASTWriter::wasDeclEmitted(const Decl *D) const { + assert(D); + + assert(DoneWritingDeclsAndTypes && + "wasDeclEmitted should only be called after writing declarations"); + + if (D->isFromASTFile()) + return true; + + bool Emitted = DeclIDs.contains(D); + assert((Emitted || GeneratingReducedBMI) && + "The declaration can only be omitted in reduced BMI."); + return Emitted; +} + void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) { assert(ID); assert(D); @@ -7425,6 +7518,12 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { writeEnum(DC->getDefaultClauseKind()); return; } + case OpenACCClauseKind::If: { + const auto *IC = cast(C); + writeSourceLocation(IC->getLParenLoc()); + AddStmt(const_cast(IC->getConditionExpr())); + return; + } case OpenACCClauseKind::Finalize: case OpenACCClauseKind::IfPresent: case OpenACCClauseKind::Seq: @@ -7433,7 +7532,6 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { case OpenACCClauseKind::Worker: case OpenACCClauseKind::Vector: case OpenACCClauseKind::NoHost: - case OpenACCClauseKind::If: case OpenACCClauseKind::Self: case OpenACCClauseKind::Copy: case OpenACCClauseKind::UseDevice: diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 87e773be54fae9a9b25f5a3621b6178a191a9bd1..276b6257f1d8417bb3ce0581f63cf3d44871e053 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -749,8 +749,15 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { if (!ShouldSkipCheckingODR) Record.push_back(D->getODRHash()); - if (D->isDefaulted()) { - if (auto *FDI = D->getDefaultedFunctionInfo()) { + if (D->isDefaulted() || D->isDeletedAsWritten()) { + if (auto *FDI = D->getDefalutedOrDeletedInfo()) { + // Store both that there is an DefaultedOrDeletedInfo and whether it + // contains a DeletedMessage. + StringLiteral *DeletedMessage = FDI->getDeletedMessage(); + Record.push_back(1 | (DeletedMessage ? 2 : 0)); + if (DeletedMessage) + Record.AddStmt(DeletedMessage); + Record.push_back(FDI->getUnqualifiedLookups().size()); for (DeclAccessPair P : FDI->getUnqualifiedLookups()) { Record.AddDeclRef(P.getDecl()); @@ -1719,6 +1726,15 @@ void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (D->isFirstDecl()) AddTemplateSpecializations(D); + + // Force emitting the corresponding deduction guide in reduced BMI mode. + // Otherwise, the deduction guide may be optimized out incorrectly. + if (Writer.isGeneratingReducedBMI()) { + auto Name = Context.DeclarationNames.getCXXDeductionGuideName(D); + for (auto *DG : D->getDeclContext()->noload_lookup(Name)) + Writer.GetDeclRef(DG); + } + Code = serialization::DECL_CLASS_TEMPLATE; } @@ -1963,8 +1979,22 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC) { "You need to update the serializer after you change the " "DeclContextBits"); - Record.AddOffset(Writer.WriteDeclContextLexicalBlock(Context, DC)); - Record.AddOffset(Writer.WriteDeclContextVisibleBlock(Context, DC)); + uint64_t LexicalOffset = 0; + uint64_t VisibleOffset = 0; + + if (Writer.isGeneratingReducedBMI() && isa(DC) && + cast(DC)->isFromExplicitGlobalModule()) { + // In reduced BMI, delay writing lexical and visible block for namespace + // in the global module fragment. See the comments of DelayedNamespace for + // details. + Writer.DelayedNamespace.push_back(cast(DC)); + } else { + LexicalOffset = Writer.WriteDeclContextLexicalBlock(Context, DC); + VisibleOffset = Writer.WriteDeclContextVisibleBlock(Context, DC); + } + + Record.AddOffset(LexicalOffset); + Record.AddOffset(VisibleOffset); } const Decl *ASTWriter::getFirstLocalDecl(const Decl *D) { diff --git a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp index 65a2ec4076fdf69d64f87c22c9c4c42ca7b72a0d..009c0d3fb93686b3b0306bceabfaceb2a4133ae5 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp @@ -770,6 +770,10 @@ const CXXRecordDecl *getCXXRecordDecl(ProgramStateRef State, Type = RefT->getPointeeType(); } + if (const auto *PtrT = Type->getAs()) { + Type = PtrT->getPointeeType(); + } + return Type->getUnqualifiedDesugaredType()->getAsCXXRecordDecl(); } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 504fd7f05e0f99babc8767246c305bf592732f1a..c50db1e0e2f863e30e6736daa5adffbcbcf4c0fc 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -229,7 +229,7 @@ SVal ExprEngine::computeObjectUnderConstruction( // We are on the top frame of the analysis. We do not know where is the // object returned to. Conjure a symbolic region for the return value. // TODO: We probably need a new MemRegion kind to represent the storage - // of that SymbolicRegion, so that we cound produce a fancy symbol + // of that SymbolicRegion, so that we could produce a fancy symbol // instead of an anonymous conjured symbol. // TODO: Do we need to track the region to avoid having it dead // too early? It does die too early, at least in C++17, but because diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp index 9b7812a1adb9e32e8ec532d94eabbe494effe142..0cab17a34244069f1d1f380e42651eee67755334 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -113,8 +113,8 @@ DependencyScanningFilesystemSharedCache::CacheShard::findEntryByFilename( StringRef Filename) const { assert(llvm::sys::path::is_absolute_gnu(Filename)); std::lock_guard LockGuard(CacheLock); - auto It = EntriesByFilename.find(Filename); - return It == EntriesByFilename.end() ? nullptr : It->getValue(); + auto It = CacheByFilename.find(Filename); + return It == CacheByFilename.end() ? nullptr : It->getValue().first; } const CachedFileSystemEntry * @@ -130,11 +130,16 @@ DependencyScanningFilesystemSharedCache::CacheShard:: getOrEmplaceEntryForFilename(StringRef Filename, llvm::ErrorOr Stat) { std::lock_guard LockGuard(CacheLock); - auto Insertion = EntriesByFilename.insert({Filename, nullptr}); - if (Insertion.second) - Insertion.first->second = + auto [It, Inserted] = CacheByFilename.insert({Filename, {nullptr, nullptr}}); + auto &[CachedEntry, CachedRealPath] = It->getValue(); + if (!CachedEntry) { + // The entry is not present in the shared cache. Either the cache doesn't + // know about the file at all, or it only knows about its real path. + assert((Inserted || CachedRealPath) && "existing file with empty pair"); + CachedEntry = new (EntryStorage.Allocate()) CachedFileSystemEntry(std::move(Stat)); - return *Insertion.first->second; + } + return *CachedEntry; } const CachedFileSystemEntry & @@ -142,16 +147,17 @@ DependencyScanningFilesystemSharedCache::CacheShard::getOrEmplaceEntryForUID( llvm::sys::fs::UniqueID UID, llvm::vfs::Status Stat, std::unique_ptr Contents) { std::lock_guard LockGuard(CacheLock); - auto Insertion = EntriesByUID.insert({UID, nullptr}); - if (Insertion.second) { + auto [It, Inserted] = EntriesByUID.insert({UID, nullptr}); + auto &CachedEntry = It->getSecond(); + if (Inserted) { CachedFileContents *StoredContents = nullptr; if (Contents) StoredContents = new (ContentsStorage.Allocate()) CachedFileContents(std::move(Contents)); - Insertion.first->second = new (EntryStorage.Allocate()) + CachedEntry = new (EntryStorage.Allocate()) CachedFileSystemEntry(std::move(Stat), StoredContents); } - return *Insertion.first->second; + return *CachedEntry; } const CachedFileSystemEntry & @@ -159,7 +165,40 @@ DependencyScanningFilesystemSharedCache::CacheShard:: getOrInsertEntryForFilename(StringRef Filename, const CachedFileSystemEntry &Entry) { std::lock_guard LockGuard(CacheLock); - return *EntriesByFilename.insert({Filename, &Entry}).first->getValue(); + auto [It, Inserted] = CacheByFilename.insert({Filename, {&Entry, nullptr}}); + auto &[CachedEntry, CachedRealPath] = It->getValue(); + if (!Inserted || !CachedEntry) + CachedEntry = &Entry; + return *CachedEntry; +} + +const CachedRealPath * +DependencyScanningFilesystemSharedCache::CacheShard::findRealPathByFilename( + StringRef Filename) const { + assert(llvm::sys::path::is_absolute_gnu(Filename)); + std::lock_guard LockGuard(CacheLock); + auto It = CacheByFilename.find(Filename); + return It == CacheByFilename.end() ? nullptr : It->getValue().second; +} + +const CachedRealPath &DependencyScanningFilesystemSharedCache::CacheShard:: + getOrEmplaceRealPathForFilename(StringRef Filename, + llvm::ErrorOr RealPath) { + std::lock_guard LockGuard(CacheLock); + + const CachedRealPath *&StoredRealPath = CacheByFilename[Filename].second; + if (!StoredRealPath) { + auto OwnedRealPath = [&]() -> CachedRealPath { + if (!RealPath) + return RealPath.getError(); + return RealPath->str(); + }(); + + StoredRealPath = new (RealPathStorage.Allocate()) + CachedRealPath(std::move(OwnedRealPath)); + } + + return *StoredRealPath; } static bool shouldCacheStatFailures(StringRef Filename) { @@ -233,24 +272,15 @@ DependencyScanningWorkerFilesystem::computeAndStoreResult( llvm::ErrorOr DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry( StringRef OriginalFilename) { - StringRef FilenameForLookup; SmallString<256> PathBuf; - if (llvm::sys::path::is_absolute_gnu(OriginalFilename)) { - FilenameForLookup = OriginalFilename; - } else if (!WorkingDirForCacheLookup) { - return WorkingDirForCacheLookup.getError(); - } else { - StringRef RelFilename = OriginalFilename; - RelFilename.consume_front("./"); - PathBuf = *WorkingDirForCacheLookup; - llvm::sys::path::append(PathBuf, RelFilename); - FilenameForLookup = PathBuf.str(); - } - assert(llvm::sys::path::is_absolute_gnu(FilenameForLookup)); + auto FilenameForLookup = tryGetFilenameForLookup(OriginalFilename, PathBuf); + if (!FilenameForLookup) + return FilenameForLookup.getError(); + if (const auto *Entry = - findEntryByFilenameWithWriteThrough(FilenameForLookup)) + findEntryByFilenameWithWriteThrough(*FilenameForLookup)) return EntryRef(OriginalFilename, *Entry).unwrapError(); - auto MaybeEntry = computeAndStoreResult(OriginalFilename, FilenameForLookup); + auto MaybeEntry = computeAndStoreResult(OriginalFilename, *FilenameForLookup); if (!MaybeEntry) return MaybeEntry.getError(); return EntryRef(OriginalFilename, *MaybeEntry).unwrapError(); @@ -270,6 +300,17 @@ DependencyScanningWorkerFilesystem::status(const Twine &Path) { return Result->getStatus(); } +bool DependencyScanningWorkerFilesystem::exists(const Twine &Path) { + // While some VFS overlay filesystems may implement more-efficient + // mechanisms for `exists` queries, `DependencyScanningWorkerFilesystem` + // typically wraps `RealFileSystem` which does not specialize `exists`, + // so it is not likely to benefit from such optimizations. Instead, + // it is more-valuable to have this query go through the + // cached-`status` code-path of the `DependencyScanningWorkerFilesystem`. + llvm::ErrorOr Status = status(Path); + return Status && Status->exists(); +} + namespace { /// The VFS that is used by clang consumes the \c CachedFileSystemEntry using @@ -330,6 +371,54 @@ DependencyScanningWorkerFilesystem::openFileForRead(const Twine &Path) { return DepScanFile::create(Result.get()); } +std::error_code +DependencyScanningWorkerFilesystem::getRealPath(const Twine &Path, + SmallVectorImpl &Output) { + SmallString<256> OwnedFilename; + StringRef OriginalFilename = Path.toStringRef(OwnedFilename); + + SmallString<256> PathBuf; + auto FilenameForLookup = tryGetFilenameForLookup(OriginalFilename, PathBuf); + if (!FilenameForLookup) + return FilenameForLookup.getError(); + + auto HandleCachedRealPath = + [&Output](const CachedRealPath &RealPath) -> std::error_code { + if (!RealPath) + return RealPath.getError(); + Output.assign(RealPath->begin(), RealPath->end()); + return {}; + }; + + // If we already have the result in local cache, no work required. + if (const auto *RealPath = + LocalCache.findRealPathByFilename(*FilenameForLookup)) + return HandleCachedRealPath(*RealPath); + + // If we have the result in the shared cache, cache it locally. + auto &Shard = SharedCache.getShardForFilename(*FilenameForLookup); + if (const auto *ShardRealPath = + Shard.findRealPathByFilename(*FilenameForLookup)) { + const auto &RealPath = LocalCache.insertRealPathForFilename( + *FilenameForLookup, *ShardRealPath); + return HandleCachedRealPath(RealPath); + } + + // If we don't know the real path, compute it... + std::error_code EC = getUnderlyingFS().getRealPath(OriginalFilename, Output); + llvm::ErrorOr ComputedRealPath = EC; + if (!EC) + ComputedRealPath = StringRef{Output.data(), Output.size()}; + + // ...and try to write it into the shared cache. In case some other thread won + // this race and already wrote its own result there, just adopt it. Write + // whatever is in the shared cache into the local one. + const auto &RealPath = Shard.getOrEmplaceRealPathForFilename( + *FilenameForLookup, ComputedRealPath); + return HandleCachedRealPath( + LocalCache.insertRealPathForFilename(*FilenameForLookup, RealPath)); +} + std::error_code DependencyScanningWorkerFilesystem::setCurrentWorkingDirectory( const Twine &Path) { std::error_code EC = ProxyFileSystem::setCurrentWorkingDirectory(Path); @@ -351,4 +440,24 @@ void DependencyScanningWorkerFilesystem::updateWorkingDirForCacheLookup() { llvm::sys::path::is_absolute_gnu(*WorkingDirForCacheLookup)); } +llvm::ErrorOr +DependencyScanningWorkerFilesystem::tryGetFilenameForLookup( + StringRef OriginalFilename, llvm::SmallVectorImpl &PathBuf) const { + StringRef FilenameForLookup; + if (llvm::sys::path::is_absolute_gnu(OriginalFilename)) { + FilenameForLookup = OriginalFilename; + } else if (!WorkingDirForCacheLookup) { + return WorkingDirForCacheLookup.getError(); + } else { + StringRef RelFilename = OriginalFilename; + RelFilename.consume_front("./"); + PathBuf.assign(WorkingDirForCacheLookup->begin(), + WorkingDirForCacheLookup->end()); + llvm::sys::path::append(PathBuf, RelFilename); + FilenameForLookup = StringRef{PathBuf.begin(), PathBuf.size()}; + } + assert(llvm::sys::path::is_absolute_gnu(FilenameForLookup)); + return FilenameForLookup; +} + const char DependencyScanningWorkerFilesystem::ID = 0; diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index 94ccbd3351b09d51dfc595265869b8d43bde364c..e19f19b2528c1540912bc3fe359a0193fe66c977 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -154,6 +154,26 @@ void ModuleDepCollector::addOutputPaths(CowCompilerInvocation &CI, } } +void dependencies::resetBenignCodeGenOptions(frontend::ActionKind ProgramAction, + const LangOptions &LangOpts, + CodeGenOptions &CGOpts) { + // TODO: Figure out better way to set options to their default value. + if (ProgramAction == frontend::GenerateModule) { + CGOpts.MainFileName.clear(); + CGOpts.DwarfDebugFlags.clear(); + } + if (ProgramAction == frontend::GeneratePCH || + (ProgramAction == frontend::GenerateModule && !LangOpts.ModulesCodegen)) { + CGOpts.DebugCompilationDir.clear(); + CGOpts.CoverageCompilationDir.clear(); + CGOpts.CoverageDataFile.clear(); + CGOpts.CoverageNotesFile.clear(); + CGOpts.ProfileInstrumentUsePath.clear(); + CGOpts.SampleProfileFile.clear(); + CGOpts.ProfileRemappingFile.clear(); + } +} + static CowCompilerInvocation makeCommonInvocationForModuleBuild(CompilerInvocation CI) { CI.resetNonModularOptions(); @@ -167,18 +187,8 @@ makeCommonInvocationForModuleBuild(CompilerInvocation CI) { // LLVM options are not going to affect the AST CI.getFrontendOpts().LLVMArgs.clear(); - // TODO: Figure out better way to set options to their default value. - CI.getCodeGenOpts().MainFileName.clear(); - CI.getCodeGenOpts().DwarfDebugFlags.clear(); - if (!CI.getLangOpts().ModulesCodegen) { - CI.getCodeGenOpts().DebugCompilationDir.clear(); - CI.getCodeGenOpts().CoverageCompilationDir.clear(); - CI.getCodeGenOpts().CoverageDataFile.clear(); - CI.getCodeGenOpts().CoverageNotesFile.clear(); - CI.getCodeGenOpts().ProfileInstrumentUsePath.clear(); - CI.getCodeGenOpts().SampleProfileFile.clear(); - CI.getCodeGenOpts().ProfileRemappingFile.clear(); - } + resetBenignCodeGenOptions(frontend::GenerateModule, CI.getLangOpts(), + CI.getCodeGenOpts()); // Map output paths that affect behaviour to "-" so their existence is in the // context hash. The final path will be computed in addOutputPaths. @@ -342,6 +352,8 @@ static bool needsModules(FrontendInputFile FIF) { void ModuleDepCollector::applyDiscoveredDependencies(CompilerInvocation &CI) { CI.clearImplicitModuleBuildOptions(); + resetBenignCodeGenOptions(CI.getFrontendOpts().ProgramAction, + CI.getLangOpts(), CI.getCodeGenOpts()); if (llvm::any_of(CI.getFrontendOpts().Inputs, needsModules)) { Preprocessor &PP = ScanInstance.getPreprocessor(); diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index cdecd3e83a99796eec1462563b59d67e0fc65543..e0b18120fd2110dc61ea93ef5863d96331e87d5d 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -triple x86_64-linux -fexperimental-new-constant-interpreter -verify=expected,all -std=c11 -Wcast-qual %s -// RUN: %clang_cc1 -triple x86_64-linux -fexperimental-new-constant-interpreter -pedantic -verify=pedantic-expected,all -std=c11 -Wcast-qual %s +// RUN: %clang_cc1 -triple x86_64-linux -fexperimental-new-constant-interpreter -pedantic -verify=pedantic,pedantic-expected,all -std=c11 -Wcast-qual %s // RUN: %clang_cc1 -triple x86_64-linux -verify=ref,all -std=c11 -Wcast-qual %s -// RUN: %clang_cc1 -triple x86_64-linux -pedantic -verify=pedantic-ref,all -std=c11 -Wcast-qual %s +// RUN: %clang_cc1 -triple x86_64-linux -pedantic -verify=pedantic,pedantic-ref,all -std=c11 -Wcast-qual %s typedef __INTPTR_TYPE__ intptr_t; typedef __PTRDIFF_TYPE__ ptrdiff_t; @@ -227,3 +227,9 @@ int castViaInt[*(int*)(unsigned long)"test"]; // ref-error {{variable length arr // pedantic-ref-error {{variable length array}} \ // expected-error {{variable length array}} \ // pedantic-expected-error {{variable length array}} + +const void (*const funcp)(void) = (void*)123; // pedantic-warning {{converts between void pointer and function pointer}} +_Static_assert(funcp == (void*)0, ""); // all-error {{failed due to requirement 'funcp == (void *)0'}} \ + // pedantic-warning {{expression is not an integer constant expression}} +_Static_assert(funcp == (void*)123, ""); // pedantic-warning {{equality comparison between function pointer and void pointer}} \ + // pedantic-warning {{expression is not an integer constant expression}} diff --git a/clang/test/AST/ast-dump-attr-json.cpp b/clang/test/AST/ast-dump-attr-json.cpp index 051c2956abfdf7b29c3d77ef388683d83fb679e3..883e584bfedf07520c28b906973aea4f09ebbe48 100644 --- a/clang/test/AST/ast-dump-attr-json.cpp +++ b/clang/test/AST/ast-dump-attr-json.cpp @@ -46,6 +46,7 @@ __thread __attribute__ ((tls_model ("local-exec"))) int tls_model_var; // CHECK-NEXT: "tokLen": 11 // CHECK-NEXT: } // CHECK-NEXT: }, +// CHECK-NEXT: "isUsed": true, // CHECK-NEXT: "name": "global_decl", // CHECK-NEXT: "mangledName": "global_decl", // CHECK-NEXT: "type": { diff --git a/clang/test/AST/ast-dump-cxx2c-delete-with-message.cpp b/clang/test/AST/ast-dump-cxx2c-delete-with-message.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea16b97da23e405b04b8645d9c4483f584fd3474 --- /dev/null +++ b/clang/test/AST/ast-dump-cxx2c-delete-with-message.cpp @@ -0,0 +1,23 @@ +// Without serialization: +// RUN: %clang_cc1 -ast-dump %s | FileCheck %s +// +// With serialization: +// RUN: %clang_cc1 -emit-pch -o %t %s +// RUN: %clang_cc1 -x c++ -include-pch %t -ast-dump-all /dev/null | FileCheck %s + +struct S { + // CHECK: CXXMethodDecl {{.*}} a 'void ()' delete + // CHECK-NEXT: delete message: StringLiteral {{.*}} "foo" + void a() = delete("foo"); + + // CHECK: FunctionTemplateDecl {{.*}} b + // CHECK-NEXT: TemplateTypeParmDecl + // CHECK-NEXT: CXXMethodDecl {{.*}} b 'void ()' delete + // CHECK-NEXT: delete message: StringLiteral {{.*}} "bar" + template + void b() = delete("bar"); +}; + +// CHECK: FunctionDecl {{.*}} c 'void ()' delete +// CHECK-NEXT: delete message: StringLiteral {{.*}} "baz" +void c() = delete("baz"); diff --git a/clang/test/AST/ast-dump-default-arg-json.cpp b/clang/test/AST/ast-dump-default-arg-json.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b6a138934caf91a09a76320b6e67d391ccdd1f06 --- /dev/null +++ b/clang/test/AST/ast-dump-default-arg-json.cpp @@ -0,0 +1,2091 @@ +// RUN: %clang_cc1 -std=c++23 -triple x86_64-linux-gnu -fsyntax-only -ast-dump=json %s | FileCheck %s + +struct S { + int arr[1]; + const int *begin() const { return arr; } + const int *end() const { return &arr[1]; } + S() {} + ~S() {} +}; + +S func(const int &, const S &s = S()); + +void test() { + for (auto v : func(1)) {} +} + +// NOTE: CHECK lines have been autogenerated by gen_ast_dump_json_test.py + + +// CHECK-NOT: {{^}}Dumping +// CHECK: "kind": "TranslationUnitDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__int128_t", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__int128" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BuiltinType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__int128" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__uint128_t", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned __int128" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BuiltinType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned __int128" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__NSConstantString", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__NSConstantString_tag" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "RecordType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__NSConstantString_tag" +// CHECK-NEXT: }, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "name": "__NSConstantString_tag" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__builtin_ms_va_list", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "char *" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "PointerType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "char *" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BuiltinType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "char" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__builtin_va_list", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__va_list_tag[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ConstantArrayType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__va_list_tag[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "size": 1, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "RecordType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__va_list_tag" +// CHECK-NEXT: }, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "name": "__va_list_tag" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 3, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 103, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 235, +// CHECK-NEXT: "line": 9, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isReferenced": true, +// CHECK-NEXT: "name": "S", +// CHECK-NEXT: "tagUsed": "struct", +// CHECK-NEXT: "completeDefinition": true, +// CHECK-NEXT: "definitionData": { +// CHECK-NEXT: "canConstDefaultInit": true, +// CHECK-NEXT: "copyAssign": { +// CHECK-NEXT: "hasConstParam": true, +// CHECK-NEXT: "implicitHasConstParam": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "copyCtor": { +// CHECK-NEXT: "hasConstParam": true, +// CHECK-NEXT: "implicitHasConstParam": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "defaultCtor": { +// CHECK-NEXT: "defaultedIsConstexpr": true, +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "nonTrivial": true, +// CHECK-NEXT: "userProvided": true +// CHECK-NEXT: }, +// CHECK-NEXT: "dtor": { +// CHECK-NEXT: "nonTrivial": true, +// CHECK-NEXT: "userDeclared": true +// CHECK-NEXT: }, +// CHECK-NEXT: "hasUserDeclaredConstructor": true, +// CHECK-NEXT: "isStandardLayout": true, +// CHECK-NEXT: "moveAssign": {}, +// CHECK-NEXT: "moveCtor": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "line": 3, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 103, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "isReferenced": true, +// CHECK-NEXT: "name": "S", +// CHECK-NEXT: "tagUsed": "struct" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FieldDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 120, +// CHECK-NEXT: "line": 4, +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 116, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 125, +// CHECK-NEXT: "col": 12, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isReferenced": true, +// CHECK-NEXT: "name": "arr", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int[1]" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXMethodDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 141, +// CHECK-NEXT: "line": 5, +// CHECK-NEXT: "col": 14, +// CHECK-NEXT: "tokLen": 5 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 130, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 5 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 169, +// CHECK-NEXT: "col": 42, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "begin", +// CHECK-NEXT: "mangledName": "_ZNK1S5beginEv", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *() const" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CompoundStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 155, +// CHECK-NEXT: "col": 28, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 169, +// CHECK-NEXT: "col": 42, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ReturnStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 157, +// CHECK-NEXT: "col": 30, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "ArrayToPointerDecay", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MemberExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "name": "arr", +// CHECK-NEXT: "isArrow": true, +// CHECK-NEXT: "referencedMemberDecl": "0x{{.*}}", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXThisExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "implicit": true +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXMethodDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 184, +// CHECK-NEXT: "line": 6, +// CHECK-NEXT: "col": 14, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 173, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 5 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 214, +// CHECK-NEXT: "col": 44, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "end", +// CHECK-NEXT: "mangledName": "_ZNK1S3endEv", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *() const" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CompoundStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 196, +// CHECK-NEXT: "col": 26, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 214, +// CHECK-NEXT: "col": 44, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ReturnStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 198, +// CHECK-NEXT: "col": 28, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 211, +// CHECK-NEXT: "col": 41, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "UnaryOperator", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 205, +// CHECK-NEXT: "col": 35, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 211, +// CHECK-NEXT: "col": 41, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "isPostfix": false, +// CHECK-NEXT: "opcode": "&", +// CHECK-NEXT: "canOverflow": false, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ArraySubscriptExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 206, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 211, +// CHECK-NEXT: "col": 41, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 206, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 206, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "ArrayToPointerDecay", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MemberExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 206, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 206, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "name": "arr", +// CHECK-NEXT: "isArrow": true, +// CHECK-NEXT: "referencedMemberDecl": "0x{{.*}}", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXThisExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 206, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 206, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "implicit": true +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "IntegerLiteral", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 210, +// CHECK-NEXT: "col": 40, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 210, +// CHECK-NEXT: "col": 40, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "value": "1" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXConstructorDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 218, +// CHECK-NEXT: "line": 7, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 218, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 223, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "S", +// CHECK-NEXT: "mangledName": "_ZN1SC1Ev", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void ()" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CompoundStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 222, +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 223, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXDestructorDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 227, +// CHECK-NEXT: "line": 8, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 227, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 233, +// CHECK-NEXT: "col": 9, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "~S", +// CHECK-NEXT: "mangledName": "_ZN1SD1Ev", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void () noexcept" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CompoundStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 232, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 233, +// CHECK-NEXT: "col": 9, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXConstructorDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "line": 3, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "S", +// CHECK-NEXT: "mangledName": "_ZN1SC1ERKS_", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void (const S &)" +// CHECK-NEXT: }, +// CHECK-NEXT: "inline": true, +// CHECK-NEXT: "constexpr": true, +// CHECK-NEXT: "explicitlyDefaulted": "default", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 110, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S &" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 241, +// CHECK-NEXT: "line": 11, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 239, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 275, +// CHECK-NEXT: "col": 37, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "func", +// CHECK-NEXT: "mangledName": "_Z4funcRKiRK1S", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S (const int &, const S &)" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 257, +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 246, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 5 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 256, +// CHECK-NEXT: "col": 18, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int &" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 268, +// CHECK-NEXT: "col": 30, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 259, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 5 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "s", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S &" +// CHECK-NEXT: }, +// CHECK-NEXT: "init": "c", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ExprWithCleanups", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "cleanupsHaveSideEffects": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MaterializeTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "storageDuration": "full expression", +// CHECK-NEXT: "boundToLValueRef": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXBindTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "temp": "0x{{.*}}", +// CHECK-NEXT: "dtor": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXDestructorDecl", +// CHECK-NEXT: "name": "~S", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void () noexcept" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXTemporaryObjectExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "ctorType": { +// CHECK-NEXT: "qualType": "void ()" +// CHECK-NEXT: }, +// CHECK-NEXT: "hadMultipleCandidates": true, +// CHECK-NEXT: "constructionKind": "complete" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 284, +// CHECK-NEXT: "line": 13, +// CHECK-NEXT: "col": 6, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 279, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 321, +// CHECK-NEXT: "line": 15, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "test", +// CHECK-NEXT: "mangledName": "_Z4testv", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void ()" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CompoundStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 291, +// CHECK-NEXT: "line": 13, +// CHECK-NEXT: "col": 13, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 321, +// CHECK-NEXT: "line": 15, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXForRangeStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 295, +// CHECK-NEXT: "line": 14, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 319, +// CHECK-NEXT: "col": 27, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: {}, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 315, +// CHECK-NEXT: "col": 23, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "__range1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S &&" +// CHECK-NEXT: }, +// CHECK-NEXT: "init": "c", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ExprWithCleanups", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 315, +// CHECK-NEXT: "col": 23, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "xvalue", +// CHECK-NEXT: "cleanupsHaveSideEffects": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MaterializeTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 315, +// CHECK-NEXT: "col": 23, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "xvalue", +// CHECK-NEXT: "extendingDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__range1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S &&" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "storageDuration": "automatic", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXBindTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 315, +// CHECK-NEXT: "col": 23, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "temp": "0x{{.*}}", +// CHECK-NEXT: "dtor": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXDestructorDecl", +// CHECK-NEXT: "name": "~S", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void () noexcept" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CallExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 315, +// CHECK-NEXT: "col": 23, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S (*)(const int &, const S &)" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "FunctionToPointerDecay", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 309, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S (const int &, const S &)" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FunctionDecl", +// CHECK-NEXT: "name": "func", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S (const int &, const S &)" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MaterializeTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 314, +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 314, +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "extendingDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__range1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S &&" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "storageDuration": "automatic", +// CHECK-NEXT: "boundToLValueRef": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 314, +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 314, +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "IntegerLiteral", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 314, +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 314, +// CHECK-NEXT: "col": 22, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "value": "1" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXDefaultArgExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "hasRewrittenInit": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MaterializeTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "line": 11, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "extendingDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__range1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S &&" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "storageDuration": "automatic", +// CHECK-NEXT: "boundToLValueRef": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXBindTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "temp": "0x{{.*}}", +// CHECK-NEXT: "dtor": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXDestructorDecl", +// CHECK-NEXT: "name": "~S", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void () noexcept" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXTemporaryObjectExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 272, +// CHECK-NEXT: "col": 34, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 274, +// CHECK-NEXT: "col": 36, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "ctorType": { +// CHECK-NEXT: "qualType": "void ()" +// CHECK-NEXT: }, +// CHECK-NEXT: "hadMultipleCandidates": true, +// CHECK-NEXT: "constructionKind": "complete" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "line": 14, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "__begin1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "init": "c", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXMemberCallExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MemberExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "name": "begin", +// CHECK-NEXT: "isArrow": false, +// CHECK-NEXT: "referencedMemberDecl": "0x{{.*}}", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__range1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S &&" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "__end1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "init": "c", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXMemberCallExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MemberExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "name": "end", +// CHECK-NEXT: "isArrow": false, +// CHECK-NEXT: "referencedMemberDecl": "0x{{.*}}", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__range1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "S &&" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BinaryOperator", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "bool" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "opcode": "!=", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "LValueToRValue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__begin1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "LValueToRValue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__end1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "UnaryOperator", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "isPostfix": false, +// CHECK-NEXT: "opcode": "++", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__begin1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 300, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 316, +// CHECK-NEXT: "col": 24, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 305, +// CHECK-NEXT: "col": 13, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 300, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "v", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "init": "c", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "LValueToRValue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "UnaryOperator", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "isPostfix": false, +// CHECK-NEXT: "opcode": "*", +// CHECK-NEXT: "canOverflow": false, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "LValueToRValue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 307, +// CHECK-NEXT: "col": 15, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "name": "__begin1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const int *" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CompoundStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 318, +// CHECK-NEXT: "col": 26, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 319, +// CHECK-NEXT: "col": 27, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } diff --git a/clang/test/AST/ast-dump-default-init-json.cpp b/clang/test/AST/ast-dump-default-init-json.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1058b4e3ea4d93d9cbd6003034568a0d038ceb5f --- /dev/null +++ b/clang/test/AST/ast-dump-default-init-json.cpp @@ -0,0 +1,929 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -ast-dump=json %s | FileCheck %s + +struct A { + int arr[1]; +}; + +struct B { + const A &a = A{{0}}; +}; + +void test() { + B b{}; +} + +// NOTE: CHECK lines have been autogenerated by gen_ast_dump_json_test.py + + +// CHECK-NOT: {{^}}Dumping +// CHECK: "kind": "TranslationUnitDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__int128_t", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__int128" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BuiltinType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__int128" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__uint128_t", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned __int128" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BuiltinType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned __int128" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__NSConstantString", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__NSConstantString_tag" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "RecordType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__NSConstantString_tag" +// CHECK-NEXT: }, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "name": "__NSConstantString_tag" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__builtin_ms_va_list", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "char *" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "PointerType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "char *" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BuiltinType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "char" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "__builtin_va_list", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__va_list_tag[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ConstantArrayType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__va_list_tag[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "size": 1, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "RecordType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "__va_list_tag" +// CHECK-NEXT: }, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "name": "__va_list_tag" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 99, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 3, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 92, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 117, +// CHECK-NEXT: "line": 5, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isReferenced": true, +// CHECK-NEXT: "name": "A", +// CHECK-NEXT: "tagUsed": "struct", +// CHECK-NEXT: "completeDefinition": true, +// CHECK-NEXT: "definitionData": { +// CHECK-NEXT: "canPassInRegisters": true, +// CHECK-NEXT: "copyAssign": { +// CHECK-NEXT: "hasConstParam": true, +// CHECK-NEXT: "implicitHasConstParam": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "copyCtor": { +// CHECK-NEXT: "hasConstParam": true, +// CHECK-NEXT: "implicitHasConstParam": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "defaultCtor": { +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "dtor": { +// CHECK-NEXT: "irrelevant": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "isAggregate": true, +// CHECK-NEXT: "isLiteral": true, +// CHECK-NEXT: "isPOD": true, +// CHECK-NEXT: "isStandardLayout": true, +// CHECK-NEXT: "isTrivial": true, +// CHECK-NEXT: "isTriviallyCopyable": true, +// CHECK-NEXT: "moveAssign": { +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "moveCtor": { +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 99, +// CHECK-NEXT: "line": 3, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 92, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 99, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "A", +// CHECK-NEXT: "tagUsed": "struct" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FieldDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 109, +// CHECK-NEXT: "line": 4, +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 105, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 114, +// CHECK-NEXT: "col": 12, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "arr", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int[1]" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXDestructorDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 99, +// CHECK-NEXT: "line": 3, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 99, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 99, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "isReferenced": true, +// CHECK-NEXT: "name": "~A", +// CHECK-NEXT: "mangledName": "_ZN1AD1Ev", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void () noexcept" +// CHECK-NEXT: }, +// CHECK-NEXT: "inline": true, +// CHECK-NEXT: "explicitlyDefaulted": "default" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 128, +// CHECK-NEXT: "line": 7, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 121, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 155, +// CHECK-NEXT: "line": 9, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isReferenced": true, +// CHECK-NEXT: "name": "B", +// CHECK-NEXT: "tagUsed": "struct", +// CHECK-NEXT: "completeDefinition": true, +// CHECK-NEXT: "definitionData": { +// CHECK-NEXT: "canConstDefaultInit": true, +// CHECK-NEXT: "canPassInRegisters": true, +// CHECK-NEXT: "copyAssign": { +// CHECK-NEXT: "hasConstParam": true, +// CHECK-NEXT: "implicitHasConstParam": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "copyCtor": { +// CHECK-NEXT: "hasConstParam": true, +// CHECK-NEXT: "implicitHasConstParam": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "defaultCtor": { +// CHECK-NEXT: "defaultedIsConstexpr": true, +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "isConstexpr": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "nonTrivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "dtor": { +// CHECK-NEXT: "irrelevant": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "hasConstexprNonCopyMoveConstructor": true, +// CHECK-NEXT: "isAggregate": true, +// CHECK-NEXT: "isLiteral": true, +// CHECK-NEXT: "isTriviallyCopyable": true, +// CHECK-NEXT: "moveAssign": { +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: }, +// CHECK-NEXT: "moveCtor": { +// CHECK-NEXT: "exists": true, +// CHECK-NEXT: "needsImplicit": true, +// CHECK-NEXT: "simple": true, +// CHECK-NEXT: "trivial": true +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 128, +// CHECK-NEXT: "line": 7, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 121, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 128, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "B", +// CHECK-NEXT: "tagUsed": "struct" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FieldDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 143, +// CHECK-NEXT: "line": 8, +// CHECK-NEXT: "col": 12, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 134, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 5 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "a", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A &" +// CHECK-NEXT: }, +// CHECK-NEXT: "hasInClassInitializer": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ExprWithCleanups", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MaterializeTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "extendingDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FieldDecl", +// CHECK-NEXT: "name": "a", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A &" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "storageDuration": "automatic", +// CHECK-NEXT: "boundToLValueRef": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXFunctionalCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "InitListExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 148, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "InitListExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 149, +// CHECK-NEXT: "col": 18, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 151, +// CHECK-NEXT: "col": 20, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "IntegerLiteral", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 150, +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 150, +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "value": "0" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 164, +// CHECK-NEXT: "line": 11, +// CHECK-NEXT: "col": 6, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 159, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 182, +// CHECK-NEXT: "line": 13, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "test", +// CHECK-NEXT: "mangledName": "_Z4testv", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void ()" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CompoundStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 171, +// CHECK-NEXT: "line": 11, +// CHECK-NEXT: "col": 13, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 182, +// CHECK-NEXT: "line": 13, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 175, +// CHECK-NEXT: "line": 12, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 180, +// CHECK-NEXT: "col": 8, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 177, +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 175, +// CHECK-NEXT: "col": 3, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 179, +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "b", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "B" +// CHECK-NEXT: }, +// CHECK-NEXT: "init": "list", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "InitListExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 178, +// CHECK-NEXT: "col": 6, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 179, +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "B" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXDefaultInitExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 179, +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 179, +// CHECK-NEXT: "col": 7, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "hasRewrittenInit": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ExprWithCleanups", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "line": 8, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "MaterializeTemporaryExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "lvalue", +// CHECK-NEXT: "extendingDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FieldDecl", +// CHECK-NEXT: "name": "a", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A &" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "storageDuration": "automatic", +// CHECK-NEXT: "boundToLValueRef": true, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ImplicitCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXFunctionalCastExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 147, +// CHECK-NEXT: "col": 16, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "castKind": "NoOp", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "InitListExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 148, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 152, +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "A" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "InitListExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 149, +// CHECK-NEXT: "col": 18, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 151, +// CHECK-NEXT: "col": 20, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int[1]" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "IntegerLiteral", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 150, +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 150, +// CHECK-NEXT: "col": 19, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "value": "0" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } diff --git a/clang/test/AST/ast-dump-default-init.cpp b/clang/test/AST/ast-dump-default-init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9fe945ee6e93243f3d97e7afa29c87452790cb15 --- /dev/null +++ b/clang/test/AST/ast-dump-default-init.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -ast-dump %s | FileCheck %s + +struct A { + int arr[1]; +}; + +struct B { + const A &a = A{{0}}; +}; + +void test() { + B b{}; +} +// CHECK: -CXXDefaultInitExpr 0x{{[^ ]*}} <{{.*}}> 'const A' lvalue has rewritten init +// CHECK-NEXT: `-ExprWithCleanups 0x{{[^ ]*}} <{{.*}}> 'const A' lvalue +// CHECK-NEXT: `-MaterializeTemporaryExpr 0x{{[^ ]*}} <{{.*}}> 'const A' lvalue extended by Field 0x{{[^ ]*}} 'a' 'const A &' +// CHECK-NEXT: `-ImplicitCastExpr 0x{{[^ ]*}} <{{.*}}> 'const A' +// CHECK-NEXT: `-CXXFunctionalCastExpr 0x{{[^ ]*}} <{{.*}}> 'A' functional cast to A +// CHECK-NEXT: `-InitListExpr 0x{{[^ ]*}} <{{.*}}> 'A' +// CHECK-NEXT: `-InitListExpr 0x{{[^ ]*}} <{{.*}}> 'int[1]' +// CHECK-NEXT: `-IntegerLiteral 0x{{[^ ]*}} <{{.*}}> 'int' 0 diff --git a/clang/test/AST/ast-dump-for-range-lifetime.cpp b/clang/test/AST/ast-dump-for-range-lifetime.cpp index 88b838268be2e06061a509712bece63015ef3442..0e92b6990ed504eace65e2aa42b2a325804ff630 100644 --- a/clang/test/AST/ast-dump-for-range-lifetime.cpp +++ b/clang/test/AST/ast-dump-for-range-lifetime.cpp @@ -132,6 +132,9 @@ void test4() { // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'int (&(const A &))[3]' lvalue Function {{.*}} 'default_arg_fn' 'int (&(const A &))[3]' // CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <> 'const A':'const P2718R0::A' lvalue has rewritten init // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'A':'P2718R0::A' 'void ()' for (auto e : default_arg_fn()) bar(e); } @@ -179,10 +182,19 @@ void test5() { // CHECK-NEXT: | | | | `-CXXTemporaryObjectExpr {{.*}} 'A':'P2718R0::A' 'void ()' // CHECK-NEXT: | | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init // CHECK-NEXT: | | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' + // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' // CHECK-NEXT: | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' // CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' for (auto e : default_arg_fn(foo(foo(foo(A()))))) bar(e); } @@ -219,10 +231,19 @@ void test6() { // CHECK-NEXT: | | | | `-CXXTemporaryObjectExpr {{.*}} 'C':'P2718R0::C' 'void ()' // CHECK-NEXT: | | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init // CHECK-NEXT: | | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&' + // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' + // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' // CHECK-NEXT: | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&' + // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' // CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' for (auto e : C(0, C(0, C(0, C())))) bar(e); } diff --git a/clang/test/AST/ast-print-cxx2c-delete-with-message.cpp b/clang/test/AST/ast-print-cxx2c-delete-with-message.cpp new file mode 100644 index 0000000000000000000000000000000000000000..11e037e4d7443ec7abfc183e91539a05482f618c --- /dev/null +++ b/clang/test/AST/ast-print-cxx2c-delete-with-message.cpp @@ -0,0 +1,18 @@ +// Without serialization: +// RUN: %clang_cc1 -ast-print %s | FileCheck %s +// +// With serialization: +// RUN: %clang_cc1 -emit-pch -o %t %s +// RUN: %clang_cc1 -x c++ -include-pch %t -ast-print /dev/null | FileCheck %s + +// CHECK: struct S { +struct S { + // CHECK-NEXT: void a() = delete("foo"); + void a() = delete("foo"); + + // CHECK-NEXT: template T b() = delete("bar"); + template T b() = delete("bar"); +}; + +// CHECK: void c() = delete("baz"); +void c() = delete("baz"); diff --git a/clang/test/Analysis/invalidated-iterator.cpp b/clang/test/Analysis/invalidated-iterator.cpp index 778a8e01d99380ced8005e6dc926aa163249d803..c940dbf7276d343c2895f198978de8ad0b427e7e 100644 --- a/clang/test/Analysis/invalidated-iterator.cpp +++ b/clang/test/Analysis/invalidated-iterator.cpp @@ -130,6 +130,14 @@ struct cont_with_ptr_iterator { T* erase(T*); }; +void invalidated_access_via_end_iterator_after_push_back() { + cont_with_ptr_iterator C; + C.push_back(1); + auto i = C.end(); + C.push_back(2); + auto j = i[-1]; // expected-warning{{Invalidated iterator accessed}} +} + void invalidated_dereference_end_ptr_iterator(cont_with_ptr_iterator &C) { auto i = C.begin(); C.erase(i); @@ -196,4 +204,4 @@ void invalidated_subscript_end_ptr_iterator(cont_with_ptr_iterator &C) { auto i = C.begin(); C.erase(i); (void) i[1]; // expected-warning{{Invalidated iterator accessed}} -} +} \ No newline at end of file diff --git a/clang/test/C/C99/n809.c b/clang/test/C/C99/n809.c new file mode 100644 index 0000000000000000000000000000000000000000..7297443a777ccf9205a1961deea58ad2147a7edc --- /dev/null +++ b/clang/test/C/C99/n809.c @@ -0,0 +1,122 @@ +// RUN: %clang_cc1 -verify -std=c99 %s + +/* WG14 N620, N638, N657, N694, N809: Partial + * Complex and imaginary support in + * + * NB: Clang supports _Complex but not _Imaginary. In C99, _Complex support is + * required outside of freestanding, but _Imaginary support is fully optional. + * In C11, both are made fully optional. + * + * NB: _Complex support requires an underlying support library such as + * compiler-rt to provide functions like __divsc3. Compiler-rt is not supported + * on Windows. + * + * Because the functionality is so intertwined between the various papers, + * we're testing all of the functionality in one file. + */ + +// Demonstrate that we support spelling complex floating-point objects. +float _Complex f1; +_Complex float f2; + +double _Complex d1; +_Complex double d2; + +long double _Complex ld1; +_Complex long double ld2; + +// Show that we don't support spelling imaginary types. +float _Imaginary fi1; // expected-error {{imaginary types are not supported}} +_Imaginary float fi2; // expected-error {{imaginary types are not supported}} + +double _Imaginary di1; // expected-error {{imaginary types are not supported}} +_Imaginary double di2; // expected-error {{imaginary types are not supported}} + +long double _Imaginary ldi1; // expected-error {{imaginary types are not supported}} +_Imaginary long double ldi2; // expected-error {{imaginary types are not supported}} + +// Each complex type has the same representation and alignment as an array +// containing two elements of the corresponding real type. Note, it is not +// mandatory that the alignment of a structure containing an array of two +// elements has the same alignment as an array of two elements outside of a +// structure, but this is a property Clang supports. +_Static_assert(sizeof(float _Complex) == sizeof(struct { float mem[2]; }), ""); +_Static_assert(_Alignof(float _Complex) == _Alignof(struct { float mem[2]; }), ""); + +_Static_assert(sizeof(double _Complex) == sizeof(struct { double mem[2]; }), ""); +_Static_assert(_Alignof(double _Complex) == _Alignof(struct { double mem[2]; }), ""); + +_Static_assert(sizeof(long double _Complex) == sizeof(struct { long double mem[2]; }), ""); +_Static_assert(_Alignof(long double _Complex) == _Alignof(struct { long double mem[2]; }), ""); + +// The first element corresponds to the real part and the second element +// corresponds to the imaginary part. +_Static_assert(__real((float _Complex){ 1.0f, 2.0f }) == 1.0f, ""); +_Static_assert(__imag((float _Complex){ 1.0f, 2.0f }) == 2.0f, ""); + +_Static_assert(__real((double _Complex){ 1.0, 2.0 }) == 1.0, ""); +_Static_assert(__imag((double _Complex){ 1.0, 2.0 }) == 2.0, ""); + +_Static_assert(__real((long double _Complex){ 1.0L, 2.0L }) == 1.0L, ""); +_Static_assert(__imag((long double _Complex){ 1.0L, 2.0L }) == 2.0L, ""); + +// When a real value is converted to a complex value, the real part follows the +// usual conversion rules and the imaginary part should be zero. +_Static_assert(__real((float _Complex)1.0f) == 1.0f, ""); +_Static_assert(__imag((float _Complex)1.0f) == 0.0f, ""); + +_Static_assert(__real((double _Complex)1.0f) == 1.0, ""); +_Static_assert(__imag((double _Complex)1.0f) == 0.0, ""); + +_Static_assert(__real((long double _Complex)1.0f) == 1.0L, ""); +_Static_assert(__imag((long double _Complex)1.0f) == 0.0L, ""); + +// When a complex value is converted to a real value, the real part follows the +// usual conversion rules and the imaginary part is discarded. +_Static_assert((float)(float _Complex){ 1.0f, 2.0f } == 1.0f, ""); +_Static_assert((double)(float _Complex){ 1.0f, 2.0f } == 1.0, ""); +_Static_assert((long double)(float _Complex){ 1.0f, 2.0f } == 1.0L, ""); + +// Complex values are only equal if both the real and imaginary parts are equal. +_Static_assert((float _Complex){ 1.0f, 2.0f } == (float _Complex){ 1.0f, 2.0f }, ""); +_Static_assert((double _Complex){ 1.0, 2.0 } == (double _Complex){ 1.0, 2.0 }, ""); +_Static_assert((long double _Complex){ 1.0L, 2.0L } == (long double _Complex){ 1.0L, 2.0L }, ""); + +_Static_assert((float _Complex){ 1.0f, 2.0f } != (float _Complex){ 2.0f, 0.0f }, ""); +_Static_assert((double _Complex){ 1.0, 2.0 } != (double _Complex){ 2.0, 0.0 }, ""); +_Static_assert((long double _Complex){ 1.0L, 2.0L } != (long double _Complex){ 2.0L, 0.0L }, ""); + +// You cannot use relational operator on complex values. +int i1 = (float _Complex){ 1.0f, 2.0f } < 10; // expected-error {{invalid operands to binary expression}} +int i2 = (double _Complex){ 1.0f, 2.0f } > 10; // expected-error {{invalid operands to binary expression}} +int i3 = (long double _Complex){ 1.0f, 2.0f } <= 10; // expected-error {{invalid operands to binary expression}} +int i4 = (float _Complex){ 1.0f, 2.0f } >= 10; // expected-error {{invalid operands to binary expression}} + +// As a type specifier, _Complex cannot appear alone; however, we support it as +// an extension by assuming _Complex double. +_Complex c = 1.0f; // expected-warning {{plain '_Complex' requires a type specifier; assuming '_Complex double'}} +// Because we don't support imaginary types, we don't extend the extension to +// that type specifier. +// FIXME: the warning diagnostic here is incorrect and should not be emitted. +_Imaginary i = 1.0f; // expected-warning {{plain '_Complex' requires a type specifier; assuming '_Complex double'}} \ + expected-error {{imaginary types are not supported}} + +void func(void) { +#pragma clang diagnostic push +#pragma clang diagnostic warning "-Wpedantic" + // Increment and decrement operators have a constraint that their operand be + // a real type; Clang supports this as an extension on complex types as well. + _Complex float cf = 0.0f; + + cf++; // expected-warning {{'++' on an object of complex type is a Clang extension}} + ++cf; // expected-warning {{'++' on an object of complex type is a Clang extension}} + + cf--; // expected-warning {{'--' on an object of complex type is a Clang extension}} + --cf; // expected-warning {{'--' on an object of complex type is a Clang extension}} + + // However, unary + and - are fine, as is += 1. + (void)-cf; + (void)+cf; + cf += 1; +#pragma clang diagnostic pop +} diff --git a/clang/test/C/C99/n809_2.c b/clang/test/C/C99/n809_2.c new file mode 100644 index 0000000000000000000000000000000000000000..3bf163126521a619aa39b912cc9af6cae3dc8761 --- /dev/null +++ b/clang/test/C/C99/n809_2.c @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -ast-dump -std=c99 %s | FileCheck %s + +void variadic(int i, ...); + +void func(void) { + // CHECK: FunctionDecl {{.*}} func 'void (void)' + + // Show that we correctly convert between two complex domains. + _Complex float cf = 1.0f; + _Complex double cd; + + cd = cf; + // CHECK: BinaryOperator {{.*}} '_Complex double' '=' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cd' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex double' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex float' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cf' + + cf = cd; + // CHECK: BinaryOperator {{.*}} '_Complex float' '=' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cf' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex float' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex double' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cd' + + // Show that we correctly convert to the common type of a complex and real. + // This should convert the _Complex float to a _Complex double ("without + // change of domain" c.f. C99 6.3.1.8p1). + (void)(cf + 1.0); + // CHECK: BinaryOperator {{.*}} '_Complex double' '+' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex double' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex float' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cf' + // CHECK-NEXT: FloatingLiteral {{.*}} 'double' 1.0 + + // This should convert the float constant to double, then produce a + // _Complex double. + (void)(cd + 1.0f); + // CHECK: BinaryOperator {{.*}} '_Complex double' '+' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex double' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cd' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' + // CHECK-NEXT: FloatingLiteral {{.*}} 'float' 1.0 + + // This should convert the int constant to float, then produce a + // _Complex float. + (void)(cf + 1); + // CHECK: BinaryOperator {{.*}} '_Complex float' '+' + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex float' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cf' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1 + + // Show that we do not promote a _Complex float to _Complex double as part of + // the default argument promotions when passing to a variadic function. + variadic(1, cf); + // CHECK: CallExpr + // CHECK-NEXT: ImplicitCastExpr {{.*}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'variadic' + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1 + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Complex float' + // CHECK-NEXT: DeclRefExpr {{.*}} 'cf' +} + diff --git a/clang/test/C/C99/n809_3.c b/clang/test/C/C99/n809_3.c new file mode 100644 index 0000000000000000000000000000000000000000..f1283f5fe1632c84122d3ccdefbc62905c0e2067 --- /dev/null +++ b/clang/test/C/C99/n809_3.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -emit-llvm -std=c99 %s -o - | FileCheck %s + +// Demonstrate that statics are properly zero initialized. +static _Complex float f_global; +void func(void) { + static _Complex double d_local; + d_local = f_global; +} + +// CHECK-DAG: @func.d_local = internal global { double, double } zeroinitializer +// CHECK-DAG: @f_global = internal global { float, float } zeroinitializer + diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt index fcfca354f4a75fe53f972152a4b61fc3de1fe7e2..df34a5707da33ea8c1f8de5d7d5d8cd87fca048d 100644 --- a/clang/test/CMakeLists.txt +++ b/clang/test/CMakeLists.txt @@ -9,6 +9,7 @@ llvm_canonicalize_cmake_booleans( CLANG_ENABLE_STATIC_ANALYZER CLANG_PLUGIN_SUPPORT CLANG_SPAWN_CC1 + CLANG_ENABLE_CIR ENABLE_BACKTRACES LLVM_ENABLE_ZLIB LLVM_ENABLE_ZSTD diff --git a/clang/test/CXX/drs/dr118.cpp b/clang/test/CXX/drs/cwg118.cpp similarity index 98% rename from clang/test/CXX/drs/dr118.cpp rename to clang/test/CXX/drs/cwg118.cpp index 58aa3912c8010f308c8082736cdeff6a851a5c96..04e19ce050788cd0a270a17b729096eacc6f7d4a 100644 --- a/clang/test/CXX/drs/dr118.cpp +++ b/clang/test/CXX/drs/cwg118.cpp @@ -3,7 +3,7 @@ // RUN: %clang_cc1 -triple x86_64-linux -std=c++14 %s -pedantic-errors -emit-llvm -o - | FileCheck %s --implicit-check-not " call " // RUN: %clang_cc1 -triple x86_64-linux -std=c++1z %s -pedantic-errors -emit-llvm -o - | FileCheck %s --implicit-check-not " call " -// dr118: yes +// cwg118: yes struct S { virtual void f(); diff --git a/clang/test/CXX/drs/dr124.cpp b/clang/test/CXX/drs/cwg124.cpp similarity index 83% rename from clang/test/CXX/drs/dr124.cpp rename to clang/test/CXX/drs/cwg124.cpp index c07beb11709c712c15b2f1951934ddfbf75756e7..fef3c6085c375ff972a9c999f8d7f891df671326 100644 --- a/clang/test/CXX/drs/dr124.cpp +++ b/clang/test/CXX/drs/cwg124.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr124 { // dr124: 2.7 +namespace cwg124 { // cwg124: 2.7 extern void full_expr_fence() NOTHROW; @@ -32,20 +32,20 @@ void f() { full_expr_fence(); } -// CHECK-LABEL: define {{.*}} void @dr124::f()() -// CHECK: call void @dr124::full_expr_fence() +// CHECK-LABEL: define {{.*}} void @cwg124::f()() +// CHECK: call void @cwg124::full_expr_fence() // CHECK: br label %arrayctor.loop // CHECK-LABEL: arrayctor.loop: -// CHECK: call void @dr124::A::A() -// CHECK: call void @dr124::B::B(dr124::A) -// CHECK: call void @dr124::A::~A() +// CHECK: call void @cwg124::A::A() +// CHECK: call void @cwg124::B::B(cwg124::A) +// CHECK: call void @cwg124::A::~A() // CHECK: br {{.*}}, label %arrayctor.cont, label %arrayctor.loop // CHECK-LABEL: arrayctor.cont: -// CHECK: call void @dr124::full_expr_fence() +// CHECK: call void @cwg124::full_expr_fence() // CHECK: br label %arraydestroy.body // CHECK-LABEL: arraydestroy.body: -// CHECK: call void @dr124::B::~B() +// CHECK: call void @cwg124::B::~B() // CHECK-LABEL: } -} // namespace dr124 +} // namespace cwg124 diff --git a/clang/test/CXX/drs/dr158.cpp b/clang/test/CXX/drs/cwg158.cpp similarity index 98% rename from clang/test/CXX/drs/dr158.cpp rename to clang/test/CXX/drs/cwg158.cpp index a0a8bd05baee3bb4533fca623d145288f905036a..9301c790297e9d890735b2bf9301de74b5dcc140 100644 --- a/clang/test/CXX/drs/dr158.cpp +++ b/clang/test/CXX/drs/cwg158.cpp @@ -3,7 +3,7 @@ // RUN: %clang_cc1 -triple x86_64-linux -std=c++14 %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -triple x86_64-linux -std=c++1z %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s -// dr158: yes +// cwg158: yes // CHECK-LABEL: define {{.*}} @_Z1f const int *f(const int * const *p, int **q) { diff --git a/clang/test/CXX/drs/dr1748.cpp b/clang/test/CXX/drs/cwg1748.cpp similarity index 98% rename from clang/test/CXX/drs/dr1748.cpp rename to clang/test/CXX/drs/cwg1748.cpp index 7e04f402d266790dc4d1270a382c976c2a1c96fe..f216963d69f2a237cb5e3b6868f2743b08490a3c 100644 --- a/clang/test/CXX/drs/dr1748.cpp +++ b/clang/test/CXX/drs/cwg1748.cpp @@ -3,7 +3,7 @@ // RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | FileCheck %s // RUN: %clang_cc1 -std=c++1z %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | FileCheck %s -// dr1748: 3.7 +// cwg1748: 3.7 // FIXME: __SIZE_TYPE__ expands to 'long long' on some targets. __extension__ typedef __SIZE_TYPE__ size_t; diff --git a/clang/test/CXX/drs/dr177x.cpp b/clang/test/CXX/drs/cwg177x.cpp similarity index 95% rename from clang/test/CXX/drs/dr177x.cpp rename to clang/test/CXX/drs/cwg177x.cpp index 7b96ff0996c72b746343bba7e86f0b90c8397965..cc62bdac4cf06aaa5e26dba0724895180bc0ef6f 100644 --- a/clang/test/CXX/drs/dr177x.cpp +++ b/clang/test/CXX/drs/cwg177x.cpp @@ -4,9 +4,9 @@ // RUN: %clang_cc1 -std=c++1z %s -fexceptions -fcxx-exceptions -pedantic-errors -ast-dump | FileCheck %s --check-prefixes=CHECK,CXX11,CXX14 // RUN: %clang_cc1 -std=c++1z %s -fexceptions -fcxx-exceptions -pedantic-errors -triple i386-windows-pc -ast-dump | FileCheck %s --check-prefixes=CHECK,CXX11,CXX14 -namespace dr1772 { // dr1772: 14 +namespace cwg1772 { // cwg1772: 14 // __func__ in a lambda should name operator(), not the containing function. - // CHECK: NamespaceDecl{{.+}}dr1772 + // CHECK: NamespaceDecl{{.+}}cwg1772 #if __cplusplus >= 201103L auto x = []() { __func__; }; // CXX11: LambdaExpr @@ -30,10 +30,10 @@ namespace dr1772 { // dr1772: 14 #endif // __cplusplus >= 201103L } -namespace dr1779 { // dr1779: 14 +namespace cwg1779 { // cwg1779: 14 // __func__ in a function template, member function template, or generic // lambda should have a dependent type. - // CHECK: NamespaceDecl{{.+}}dr1779 + // CHECK: NamespaceDecl{{.+}}cwg1779 template void FuncTemplate() { diff --git a/clang/test/CXX/drs/dr1807.cpp b/clang/test/CXX/drs/cwg1807.cpp similarity index 83% rename from clang/test/CXX/drs/dr1807.cpp rename to clang/test/CXX/drs/cwg1807.cpp index 81e1e8ca640e3e1b940a0881e083375925b008a8..59edacc49658c61ee01e72e056d51ec4fd89e674 100644 --- a/clang/test/CXX/drs/dr1807.cpp +++ b/clang/test/CXX/drs/cwg1807.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11 // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11 -namespace dr1807 { // dr1807: 3.0 +namespace cwg1807 { // cwg1807: 3.0 struct S { S() {} ~S() {} @@ -17,12 +17,12 @@ void f() { } } -// CHECK-LABEL: define dso_local void @dr1807::f() -// CHECK: invoke void @dr1807::S::S(){{.+}} +// CHECK-LABEL: define dso_local void @cwg1807::f() +// CHECK: invoke void @cwg1807::S::S(){{.+}} // CHECK-NEXT: {{.+}} unwind label %lpad // CHECK-LABEL: lpad: // CHECK: br {{.+}}, label {{.+}}, label %arraydestroy.body // CHECK-LABEL: arraydestroy.body: // CHECK: [[ARRAYDESTROY_ELEMENT:%.*]] = getelementptr {{.+}}, i64 -1 -// CXX98-NEXT: invoke void @dr1807::S::~S()({{.*}}[[ARRAYDESTROY_ELEMENT]]) -// SINCE-CXX11-NEXT: call void @dr1807::S::~S()({{.*}}[[ARRAYDESTROY_ELEMENT]]) +// CXX98-NEXT: invoke void @cwg1807::S::~S()({{.*}}[[ARRAYDESTROY_ELEMENT]]) +// SINCE-CXX11-NEXT: call void @cwg1807::S::~S()({{.*}}[[ARRAYDESTROY_ELEMENT]]) diff --git a/clang/test/CXX/drs/dr185.cpp b/clang/test/CXX/drs/cwg185.cpp similarity index 85% rename from clang/test/CXX/drs/dr185.cpp rename to clang/test/CXX/drs/cwg185.cpp index aff00f1a8764ab9c2a5393f1b83a5cfa0cfb6cb8..8ab5bc5d28f821b0f1770f56a71cae7f461cb55c 100644 --- a/clang/test/CXX/drs/dr185.cpp +++ b/clang/test/CXX/drs/cwg185.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr185 { // dr185: 2.7 +namespace cwg185 { // cwg185: 2.7 struct A { mutable int value; explicit A(int i) : value(i) {} @@ -20,11 +20,11 @@ int foo() { return n.value; } -// CHECK-LABEL: define {{.*}} i32 @dr185::foo() -// CHECK: call void @dr185::A::A(int)(ptr {{[^,]*}} %ref.tmp, {{.*}}) +// CHECK-LABEL: define {{.*}} i32 @cwg185::foo() +// CHECK: call void @cwg185::A::A(int)(ptr {{[^,]*}} %ref.tmp, {{.*}}) // CHECK: store ptr %ref.tmp, ptr %t // CHECK-NOT: %t = -// CHECK: [[DR185_T:%.+]] = load ptr, ptr %t -// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr {{[^,]*}} %n, ptr {{[^,]*}} [[DR185_T]], {{.*}}) +// CHECK: [[CWG185_T:%.+]] = load ptr, ptr %t +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr {{[^,]*}} %n, ptr {{[^,]*}} [[CWG185_T]], {{.*}}) // CHECK-LABEL: } -} // namespace dr185 +} // namespace cwg185 diff --git a/clang/test/CXX/drs/dr193.cpp b/clang/test/CXX/drs/cwg193.cpp similarity index 79% rename from clang/test/CXX/drs/dr193.cpp rename to clang/test/CXX/drs/cwg193.cpp index c010dad50e403580bd21ec136c0075e51a42adba..0a6ac38941d208a161f9cbe5e135141dbe25d2d6 100644 --- a/clang/test/CXX/drs/dr193.cpp +++ b/clang/test/CXX/drs/cwg193.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr193 { // dr193: 2.7 +namespace cwg193 { // cwg193: 2.7 struct A { ~A() NOTHROW {} }; @@ -35,12 +35,12 @@ void foo() { } // skipping over D1 (complete object destructor) -// CHECK-LABEL: define {{.*}} void @dr193::D::~D(){{.*}} -// CHECK-LABEL: define {{.*}} void @dr193::D::~D(){{.*}} -// CHECK-NOT: call void @dr193::A::~A() -// CHECK-NOT: call void @dr193::B::~B() -// CHECK: call void @dr193::C::~C() -// CHECK: call void @dr193::B::~B() -// CHECK: call void @dr193::A::~A() +// CHECK-LABEL: define {{.*}} void @cwg193::D::~D(){{.*}} +// CHECK-LABEL: define {{.*}} void @cwg193::D::~D(){{.*}} +// CHECK-NOT: call void @cwg193::A::~A() +// CHECK-NOT: call void @cwg193::B::~B() +// CHECK: call void @cwg193::C::~C() +// CHECK: call void @cwg193::B::~B() +// CHECK: call void @cwg193::A::~A() // CHECK-LABEL: } -} // namespace dr193 +} // namespace cwg193 diff --git a/clang/test/CXX/drs/dr199.cpp b/clang/test/CXX/drs/cwg199.cpp similarity index 85% rename from clang/test/CXX/drs/dr199.cpp rename to clang/test/CXX/drs/cwg199.cpp index 7517d79680c6fd89711dbf31622701fa9fbe4046..5d2e5110786f15f9065255c171c2c9460c7fd067 100644 --- a/clang/test/CXX/drs/dr199.cpp +++ b/clang/test/CXX/drs/cwg199.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr199 { // dr199: 2.8 +namespace cwg199 { // cwg199: 2.8 struct A { ~A() NOTHROW {} }; @@ -25,9 +25,9 @@ void foo() { A(), B(); } -// CHECK-LABEL: define {{.*}} void @dr199::foo() -// CHECK-NOT: call void @dr199::A::~A() -// CHECK: call void @dr199::B::~B() -// CHECK: call void @dr199::A::~A() +// CHECK-LABEL: define {{.*}} void @cwg199::foo() +// CHECK-NOT: call void @cwg199::A::~A() +// CHECK: call void @cwg199::B::~B() +// CHECK: call void @cwg199::A::~A() // CHECK-LABEL: } -} // namespace dr199 +} // namespace cwg199 diff --git a/clang/test/CXX/drs/dr201.cpp b/clang/test/CXX/drs/cwg201.cpp similarity index 82% rename from clang/test/CXX/drs/dr201.cpp rename to clang/test/CXX/drs/cwg201.cpp index 7e864981e13be70964a50ec165f8fb159b6e7744..b6cf92a1fc7489ad436cedde0e0a3021e6da9c22 100644 --- a/clang/test/CXX/drs/dr201.cpp +++ b/clang/test/CXX/drs/cwg201.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr201 { // dr201: 2.8 +namespace cwg201 { // cwg201: 2.8 extern void full_expr_fence() NOTHROW; @@ -31,12 +31,12 @@ void foo() { full_expr_fence(); } -// CHECK-LABEL: define {{.*}} void @dr201::foo() -// CHECK: call void @dr201::full_expr_fence() -// CHECK: call void @dr201::B::B(dr201::A) -// CHECK: call void @dr201::A::~A() -// CHECK: call void @dr201::full_expr_fence() -// CHECK: call void @dr201::B::~B() +// CHECK-LABEL: define {{.*}} void @cwg201::foo() +// CHECK: call void @cwg201::full_expr_fence() +// CHECK: call void @cwg201::B::B(cwg201::A) +// CHECK: call void @cwg201::A::~A() +// CHECK: call void @cwg201::full_expr_fence() +// CHECK: call void @cwg201::B::~B() // CHECK-LABEL: } -} // namespace dr201 +} // namespace cwg201 diff --git a/clang/test/CXX/drs/dr210.cpp b/clang/test/CXX/drs/cwg210.cpp similarity index 91% rename from clang/test/CXX/drs/dr210.cpp rename to clang/test/CXX/drs/cwg210.cpp index 156ee81093b43cb288999f14a02e234bd034a2a3..2c3cf61a6a5b1a16b3274677f18fa84b28c98880 100644 --- a/clang/test/CXX/drs/dr210.cpp +++ b/clang/test/CXX/drs/cwg210.cpp @@ -13,7 +13,7 @@ #pragma clang diagnostic pop #endif -namespace dr210 { // dr210: 2.7 +namespace cwg210 { // cwg210: 2.7 struct B { long i; B(); @@ -33,9 +33,9 @@ void toss(const B* b) { throw *b; } -// CHECK-LABEL: define {{.*}} void @dr210::toss(dr210::B const*) +// CHECK-LABEL: define {{.*}} void @cwg210::toss(cwg210::B const*) // CHECK: %[[EXCEPTION:.*]] = call ptr @__cxa_allocate_exception(i64 16) -// CHECK: call void @__cxa_throw(ptr %[[EXCEPTION]], ptr @typeinfo for dr210::B, ptr @dr210::B::~B()) +// CHECK: call void @__cxa_throw(ptr %[[EXCEPTION]], ptr @typeinfo for cwg210::B, ptr @cwg210::B::~B()) // CHECK-LABEL: } -} // namespace dr210 +} // namespace cwg210 diff --git a/clang/test/CXX/drs/dr2335.cpp b/clang/test/CXX/drs/cwg2335.cpp similarity index 56% rename from clang/test/CXX/drs/dr2335.cpp rename to clang/test/CXX/drs/cwg2335.cpp index 33eebb2c4a5c570640330cd8e810dc511bf47966..8b00a9d2d98a5e36bd2703a50d6662dafb199b71 100644 --- a/clang/test/CXX/drs/dr2335.cpp +++ b/clang/test/CXX/drs/cwg2335.cpp @@ -10,7 +10,7 @@ // expected-no-diagnostics #endif -namespace dr2335 { // dr2335: no drafting 2018-06 +namespace cwg2335 { // cwg2335: no drafting 2018-06 // FIXME: current consensus is that the examples are well-formed. #if __cplusplus >= 201402L namespace ex1 { @@ -25,24 +25,24 @@ namespace ex2 { template struct X {}; template struct partition_indices { static auto compute_right() { return X(); } - // since-cxx14-error@-1 {{no member 'I' in 'dr2335::ex2::partition_indices'; it has not yet been instantiated}} - // since-cxx14-note@#dr2335-ex2-right {{in instantiation of member function 'dr2335::ex2::partition_indices::compute_right' requested here}} - // since-cxx14-note@#dr2335-ex2-inst {{in instantiation of template class 'dr2335::ex2::partition_indices' requested here}} - // since-cxx14-note@#dr2335-ex2-I {{not-yet-instantiated member is declared here}} - static constexpr auto right = compute_right; // #dr2335-ex2-right - static constexpr int I = sizeof(T); // #dr2335-ex2-I + // since-cxx14-error@-1 {{no member 'I' in 'cwg2335::ex2::partition_indices'; it has not yet been instantiated}} + // since-cxx14-note@#cwg2335-ex2-right {{in instantiation of member function 'cwg2335::ex2::partition_indices::compute_right' requested here}} + // since-cxx14-note@#cwg2335-ex2-inst {{in instantiation of template class 'cwg2335::ex2::partition_indices' requested here}} + // since-cxx14-note@#cwg2335-ex2-I {{not-yet-instantiated member is declared here}} + static constexpr auto right = compute_right; // #cwg2335-ex2-right + static constexpr int I = sizeof(T); // #cwg2335-ex2-I }; -template struct partition_indices; // #dr2335-ex2-inst +template struct partition_indices; // #cwg2335-ex2-inst } // namespace ex2 namespace ex3 { struct partition_indices { - static auto compute_right() {} // #dr2335-compute_right - static constexpr auto right = compute_right; // #dr2335-ex3-right + static auto compute_right() {} // #cwg2335-compute_right + static constexpr auto right = compute_right; // #cwg2335-ex3-right // since-cxx14-error@-1 {{function 'compute_right' with deduced return type cannot be used before it is defined}} - // since-cxx14-note@#dr2335-compute_right {{'compute_right' declared here}} - // since-cxx14-error@#dr2335-ex3-right {{declaration of variable 'right' with deduced type 'const auto' requires an initializer}} + // since-cxx14-note@#cwg2335-compute_right {{'compute_right' declared here}} + // since-cxx14-error@#cwg2335-ex3-right {{declaration of variable 'right' with deduced type 'const auto' requires an initializer}} }; } // namespace ex3 #endif -} // namespace dr2335 +} // namespace cwg2335 diff --git a/clang/test/CXX/drs/dr2390.cpp b/clang/test/CXX/drs/cwg2390.cpp similarity index 98% rename from clang/test/CXX/drs/dr2390.cpp rename to clang/test/CXX/drs/cwg2390.cpp index 3931365b568cebfc2a87a2c9278fda69b84796f8..41bbd0d1c5499afbd5358da31b7fca88afa47a10 100644 --- a/clang/test/CXX/drs/dr2390.cpp +++ b/clang/test/CXX/drs/cwg2390.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -E -P %s -o - | FileCheck %s -// dr2390: 14 +// cwg2390: 14 namespace PR48462 { // Test that macro expansion of the builtin argument works. diff --git a/clang/test/CXX/drs/dr2504.cpp b/clang/test/CXX/drs/cwg2504.cpp similarity index 90% rename from clang/test/CXX/drs/dr2504.cpp rename to clang/test/CXX/drs/cwg2504.cpp index 686ea73cd6a0ee6cf2b70cada6c755b1efcbd105..fa775df327cbe261343cea672779ad0fa5277521 100644 --- a/clang/test/CXX/drs/dr2504.cpp +++ b/clang/test/CXX/drs/cwg2504.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11 // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11 -namespace dr2504 { // dr2504: no +namespace cwg2504 { // cwg2504: no #if __cplusplus >= 201103L struct V { V() = default; V(int); }; struct Q { Q(); }; @@ -27,11 +27,11 @@ void foo() { C c; } // bar is not invoked, because the V subobject is not initia // we are not supposed to unconditionally call `bar()` and call a constructor // inherited from `V`. -// SINCE-CXX11-LABEL: define linkonce_odr void @dr2504::B::B() +// SINCE-CXX11-LABEL: define linkonce_odr void @cwg2504::B::B() // SINCE-CXX11-NOT: br -// SINCE-CXX11: call noundef i32 @dr2504::bar() +// SINCE-CXX11: call noundef i32 @cwg2504::bar() // SINCE-CXX11-NOT: br -// SINCE-CXX11: call void @dr2504::A::A(int) +// SINCE-CXX11: call void @cwg2504::A::A(int) // SINCE-CXX11-LABEL: } // CHECK: {{.*}} diff --git a/clang/test/CXX/drs/dr292.cpp b/clang/test/CXX/drs/cwg292.cpp similarity index 91% rename from clang/test/CXX/drs/dr292.cpp rename to clang/test/CXX/drs/cwg292.cpp index 19caeef291fa71d356dc2e169cde785afac766e4..b05d3b92d6275fe123a393ec8637e3e73aaf6f52 100644 --- a/clang/test/CXX/drs/dr292.cpp +++ b/clang/test/CXX/drs/cwg292.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr292 { // dr292: 2.9 +namespace cwg292 { // cwg292: 2.9 extern int g(); @@ -18,13 +18,13 @@ void f() { new A(g()); } -// CHECK-LABEL: define {{.*}} void @dr292::f()() +// CHECK-LABEL: define {{.*}} void @cwg292::f()() // CHECK: %[[CALL:.+]] = call {{.*}} @operator new(unsigned long)({{.*}}) -// CHECK: invoke {{.*}} i32 @dr292::g()() +// CHECK: invoke {{.*}} i32 @cwg292::g()() // CHECK-NEXT: to {{.*}} unwind label %lpad // CHECK-LABEL: lpad: // CHECK: call void @operator delete(void*)(ptr {{.*}} %[[CALL]]) // CHECK-LABEL: eh.resume: // CHECK-LABEL: } -} // namespace dr292 +} // namespace cwg292 diff --git a/clang/test/CXX/drs/dr392.cpp b/clang/test/CXX/drs/cwg392.cpp similarity index 88% rename from clang/test/CXX/drs/dr392.cpp rename to clang/test/CXX/drs/cwg392.cpp index 26e6259f71961d39c9d54b99fb207617fdf60964..e118dd7bdb5ca088224612616ae57fc03db06570 100644 --- a/clang/test/CXX/drs/dr392.cpp +++ b/clang/test/CXX/drs/cwg392.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr392 { // dr392: 2.8 +namespace cwg392 { // cwg392: 2.8 struct A { operator bool() NOTHROW; @@ -32,9 +32,9 @@ void f() if (C().get()) {} } -} // namespace dr392 +} // namespace cwg392 -// CHECK-LABEL: define {{.*}} void @dr392::f()() -// CHECK: call {{.*}} i1 @dr392::A::operator bool() -// CHECK: call void @dr392::C::~C() +// CHECK-LABEL: define {{.*}} void @cwg392::f()() +// CHECK: call {{.*}} i1 @cwg392::A::operator bool() +// CHECK: call void @cwg392::C::~C() // CHECK-LABEL: } diff --git a/clang/test/CXX/drs/dr412.cpp b/clang/test/CXX/drs/cwg412.cpp similarity index 99% rename from clang/test/CXX/drs/dr412.cpp rename to clang/test/CXX/drs/cwg412.cpp index 8ea29135d1df825481817858bf7f87cb3df6f8d7..7e75bececac87c3935fdfad3a0470cf63fd4f15d 100644 --- a/clang/test/CXX/drs/dr412.cpp +++ b/clang/test/CXX/drs/cwg412.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -DNOEXCEPT=noexcept -DBAD_ALLOC= // RUN: %clang_cc1 -std=c++2c %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -DNOEXCEPT=noexcept -DBAD_ALLOC= -// dr412: 3.4 +// cwg412: 3.4 // lwg404: yes // lwg2340: yes diff --git a/clang/test/CXX/drs/dr438.cpp b/clang/test/CXX/drs/cwg438.cpp similarity index 94% rename from clang/test/CXX/drs/dr438.cpp rename to clang/test/CXX/drs/cwg438.cpp index a6ed39b88c2420f5741993d675498d573247b334..5f2fb7c70d879bcf9fd48573fe0383044816a269 100644 --- a/clang/test/CXX/drs/dr438.cpp +++ b/clang/test/CXX/drs/cwg438.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr438 { // dr438: 2.7 +namespace cwg438 { // cwg438: 2.7 void f() { long A[2]; @@ -14,9 +14,9 @@ void f() { A[A[0]] = 1; } -} // namespace dr438 +} // namespace cwg438 -// CHECK-LABEL: define {{.*}} void @dr438::f()() +// CHECK-LABEL: define {{.*}} void @cwg438::f()() // CHECK: [[A:%.+]] = alloca [2 x i64] // CHECK: {{.+}} = getelementptr inbounds [2 x i64], ptr [[A]], i64 0, i64 0 // CHECK: [[ARRAYIDX1:%.+]] = getelementptr inbounds [2 x i64], ptr [[A]], i64 0, i64 0 diff --git a/clang/test/CXX/drs/dr439.cpp b/clang/test/CXX/drs/cwg439.cpp similarity index 94% rename from clang/test/CXX/drs/dr439.cpp rename to clang/test/CXX/drs/cwg439.cpp index 46960af93bb9aaf012a9c1e93243bc5e71d36bbe..e409b803797fab2d3337d3e211520a2ff7d5ab62 100644 --- a/clang/test/CXX/drs/dr439.cpp +++ b/clang/test/CXX/drs/cwg439.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr439 { // dr439: 2.7 +namespace cwg439 { // cwg439: 2.7 void f() { int* p1 = new int; @@ -14,12 +14,12 @@ void f() { bool b = p1 == p2; // b will have the value true. } -} // namespace dr439 +} // namespace cwg439 // We're checking that p2 was copied from p1, and then was carried over // to the comparison without change. -// CHECK-LABEL: define {{.*}} void @dr439::f()() +// CHECK-LABEL: define {{.*}} void @cwg439::f()() // CHECK: [[P1:%.+]] = alloca ptr, align 8 // CHECK-NEXT: [[P2:%.+]] = alloca ptr, align 8 // CHECK: [[TEMP0:%.+]] = load ptr, ptr [[P1]] diff --git a/clang/test/CXX/drs/dr441.cpp b/clang/test/CXX/drs/cwg441.cpp similarity index 76% rename from clang/test/CXX/drs/dr441.cpp rename to clang/test/CXX/drs/cwg441.cpp index 6504bba689d2251a1afc177da1aba0f71b96b5fb..5f566f2301936bd119846cc72b37a966ac446a8f 100644 --- a/clang/test/CXX/drs/dr441.cpp +++ b/clang/test/CXX/drs/cwg441.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr441 { // dr441: 2.7 +namespace cwg441 { // cwg441: 2.7 struct A { A() {} @@ -17,21 +17,21 @@ int i; int& ir = i; int* ip = &i; -} // namespace dr441 +} // namespace cwg441 -// CHECK-DAG: @dr441::dynamic_init = global %"struct.dr441::A" zeroinitializer -// CHECK-DAG: @dr441::i = global i32 0 -// CHECK-DAG: @dr441::ir = constant ptr @dr441::i -// CHECK-DAG: @dr441::ip = global ptr @dr441::i -// CHECK-DAG: @llvm.global_ctors = appending global [{{.+}}] [{ {{.+}} } { {{.+}}, ptr @_GLOBAL__sub_I_dr441.cpp, {{.+}} }] +// CHECK-DAG: @cwg441::dynamic_init = global %"struct.cwg441::A" zeroinitializer +// CHECK-DAG: @cwg441::i = global i32 0 +// CHECK-DAG: @cwg441::ir = constant ptr @cwg441::i +// CHECK-DAG: @cwg441::ip = global ptr @cwg441::i +// CHECK-DAG: @llvm.global_ctors = appending global [{{.+}}] [{ {{.+}} } { {{.+}}, ptr @_GLOBAL__sub_I_cwg441.cpp, {{.+}} }] // CHECK-LABEL: define {{.*}} void @__cxx_global_var_init() // CHECK-NEXT: entry: -// CHECK-NEXT: call void @dr441::A::A()({{.*}} @dr441::dynamic_init) +// CHECK-NEXT: call void @cwg441::A::A()({{.*}} @cwg441::dynamic_init) // CHECK-NEXT: ret void // CHECK-NEXT: } -// CHECK-LABEL: define {{.*}} void @_GLOBAL__sub_I_dr441.cpp() +// CHECK-LABEL: define {{.*}} void @_GLOBAL__sub_I_cwg441.cpp() // CHECK-NEXT: entry: // CHECK-NEXT: call void @__cxx_global_var_init() // CHECK-NEXT: ret void diff --git a/clang/test/CXX/drs/dr462.cpp b/clang/test/CXX/drs/cwg462.cpp similarity index 87% rename from clang/test/CXX/drs/dr462.cpp rename to clang/test/CXX/drs/cwg462.cpp index 2b268778ea10da049d00d7e65fb47148de25f29a..bdbcacd733bbbeead08ab31099a4cef5bb7112f7 100644 --- a/clang/test/CXX/drs/dr462.cpp +++ b/clang/test/CXX/drs/cwg462.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr462 { // dr462: 2.7 +namespace cwg462 { // cwg462: 2.7 struct A { ~A() NOTHROW {} @@ -25,9 +25,9 @@ void f() { full_expr_fence(); } -} // namespace dr462 +} // namespace cwg462 -// CHECK-LABEL: define {{.*}} void @dr462::f()() -// CHECK: call void @dr462::full_expr_fence()() -// CHECK: call void @dr462::A::~A() +// CHECK-LABEL: define {{.*}} void @cwg462::f()() +// CHECK: call void @cwg462::full_expr_fence()() +// CHECK: call void @cwg462::A::~A() // CHECK-LABEL: } diff --git a/clang/test/CXX/drs/dr492.cpp b/clang/test/CXX/drs/cwg492.cpp similarity index 94% rename from clang/test/CXX/drs/dr492.cpp rename to clang/test/CXX/drs/cwg492.cpp index f53f1cb54124048ed4684eb220f6558fd1acdfec..7fc46b04d72bd33a1601414e61ad8fb8c832f80f 100644 --- a/clang/test/CXX/drs/dr492.cpp +++ b/clang/test/CXX/drs/cwg492.cpp @@ -18,7 +18,7 @@ struct type_info { }; } -namespace dr492 { // dr492: 2.7 +namespace cwg492 { // cwg492: 2.7 void f() { typeid(int).name(); @@ -27,9 +27,9 @@ void f() { typeid(const volatile int).name(); } -} // namespace dr492 +} // namespace cwg492 -// CHECK-LABEL: define {{.*}} void @dr492::f()() +// CHECK-LABEL: define {{.*}} void @cwg492::f()() // CHECK: {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int) // CHECK-NEXT: {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int) // CHECK-NEXT: {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int) diff --git a/clang/test/CXX/drs/dr519.cpp b/clang/test/CXX/drs/cwg519.cpp similarity index 95% rename from clang/test/CXX/drs/dr519.cpp rename to clang/test/CXX/drs/cwg519.cpp index 67c01d95ef7c6f89e6a71b3c8c48107985dc915c..ce8a1cc95f600b754178c4daf413bbc7cdaf3f77 100644 --- a/clang/test/CXX/drs/dr519.cpp +++ b/clang/test/CXX/drs/cwg519.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr519 { // dr519: 2.7 +namespace cwg519 { // cwg519: 2.7 void f() { int *a = 0; void *v = a; @@ -16,12 +16,12 @@ void f() { int *b = static_cast(w); bool c2 = b == static_cast(0); } -} // namespace dr519 +} // namespace cwg519 // We're checking that `null`s that were initially stored in `a` and `w` // are simply copied over all the way to respective comparisons with `null`. -// CHECK-LABEL: define {{.*}} void @dr519::f()() +// CHECK-LABEL: define {{.*}} void @cwg519::f()() // CHECK: store ptr null, ptr [[A:%.+]], // CHECK-NEXT: [[TEMP_A:%.+]] = load ptr, ptr [[A]] // CHECK-NEXT: store ptr [[TEMP_A]], ptr [[V:%.+]], diff --git a/clang/test/CXX/drs/dr571.cpp b/clang/test/CXX/drs/cwg571.cpp similarity index 91% rename from clang/test/CXX/drs/dr571.cpp rename to clang/test/CXX/drs/cwg571.cpp index 19a85b7ddc3508a7929ae31196de2ae336ee6d3d..9f0f455fb72760268b73218acfce244bf2b88d84 100644 --- a/clang/test/CXX/drs/dr571.cpp +++ b/clang/test/CXX/drs/cwg571.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr571 { // dr571: 2.7 +namespace cwg571 { // cwg571: 2.7 typedef int &ir; int n; const ir r = n; @@ -16,5 +16,5 @@ namespace dr571 { // dr571: 2.7 // Entities have external linkage by default. -// CHECK: @dr571::r = constant ptr @dr571::n -// CHECK: @dr571::r2 = constant ptr @dr571::n +// CHECK: @cwg571::r = constant ptr @cwg571::n +// CHECK: @cwg571::r2 = constant ptr @cwg571::n diff --git a/clang/test/CXX/drs/dr605.cpp b/clang/test/CXX/drs/cwg605.cpp similarity index 91% rename from clang/test/CXX/drs/dr605.cpp rename to clang/test/CXX/drs/cwg605.cpp index 6c212d8dabc06c882448fb15a6f1f10be023802c..2fd9e8155bf77b4de0bca92a2b3354e6e909575b 100644 --- a/clang/test/CXX/drs/dr605.cpp +++ b/clang/test/CXX/drs/cwg605.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr605 { // dr605: 2.7 +namespace cwg605 { // cwg605: 2.7 template static T f(T t) {} @@ -18,6 +18,6 @@ void g(int a) { f(a); } -} // namespace dr605 +} // namespace cwg605 -// CHECK: define internal {{.*}} i32 @int dr605::f(int) +// CHECK: define internal {{.*}} i32 @int cwg605::f(int) diff --git a/clang/test/CXX/drs/dr650.cpp b/clang/test/CXX/drs/cwg650.cpp similarity index 86% rename from clang/test/CXX/drs/dr650.cpp rename to clang/test/CXX/drs/cwg650.cpp index 715b4fdf04a7f01422ebae34fa7d37d504eb3f9f..dcb844095b05983e7952adeb864846a0c1e758b7 100644 --- a/clang/test/CXX/drs/dr650.cpp +++ b/clang/test/CXX/drs/cwg650.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr650 { // dr650: 2.8 +namespace cwg650 { // cwg650: 2.8 struct Q { ~Q() NOTHROW; @@ -31,10 +31,10 @@ const S& f() { return (R(), S()); } -} // namespace dr650 +} // namespace cwg650 -// CHECK-LABEL: define {{.*}} @dr650::f()() -// CHECK: call void @dr650::S::~S() -// CHECK: call void @dr650::R::~R() -// CHECK: call void @dr650::Q::~Q() +// CHECK-LABEL: define {{.*}} @cwg650::f()() +// CHECK: call void @cwg650::S::~S() +// CHECK: call void @cwg650::R::~R() +// CHECK: call void @cwg650::Q::~Q() // CHECK-LABEL: } diff --git a/clang/test/CXX/drs/dr653.cpp b/clang/test/CXX/drs/cwg653.cpp similarity index 92% rename from clang/test/CXX/drs/dr653.cpp rename to clang/test/CXX/drs/cwg653.cpp index fd1f0153bfb74e80df7c654c48858f69467bd0d9..3aeb394347ea60aac65b205378b23a8ac15480d7 100644 --- a/clang/test/CXX/drs/dr653.cpp +++ b/clang/test/CXX/drs/cwg653.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr653 { // dr653: 2.7 +namespace cwg653 { // cwg653: 2.7 union U { int a; @@ -18,8 +18,8 @@ void f(U u) { v = u; } -} // namespace dr653 +} // namespace cwg653 -// CHECK-LABEL: define {{.*}} void @dr653::f(dr653::U) +// CHECK-LABEL: define {{.*}} void @cwg653::f(cwg653::U) // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}} %v, ptr {{.*}} %u, {{.*}}) // CHECK-LABEL: } diff --git a/clang/test/CXX/drs/dr658.cpp b/clang/test/CXX/drs/cwg658.cpp similarity index 92% rename from clang/test/CXX/drs/dr658.cpp rename to clang/test/CXX/drs/cwg658.cpp index 51034c2af3bf31db28d433388034680829598a81..2f7f1ad7deda566e982df0472f0db680e6adfd9e 100644 --- a/clang/test/CXX/drs/dr658.cpp +++ b/clang/test/CXX/drs/cwg658.cpp @@ -6,17 +6,17 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr658 { // dr658: 2.7 +namespace cwg658 { // cwg658: 2.7 void f(int* p1) { char* p2 = reinterpret_cast(p1); } -} // namespace dr658 +} // namespace cwg658 // We're checking that p1 is stored into p2 without changes. -// CHECK-LABEL: define {{.*}} void @dr658::f(int*)(ptr noundef %p1) +// CHECK-LABEL: define {{.*}} void @cwg658::f(int*)(ptr noundef %p1) // CHECK: [[P1_ADDR:%.+]] = alloca ptr, align 8 // CHECK-NEXT: [[P2:%.+]] = alloca ptr, align 8 // CHECK: store ptr %p1, ptr [[P1_ADDR]] diff --git a/clang/test/CXX/drs/dr661.cpp b/clang/test/CXX/drs/cwg661.cpp similarity index 91% rename from clang/test/CXX/drs/dr661.cpp rename to clang/test/CXX/drs/cwg661.cpp index 4e97bb7088476f350fb29cb2eb1aa85cff3b8b3d..55721317107088aaf2e74717937b9b3ce691c436 100644 --- a/clang/test/CXX/drs/dr661.cpp +++ b/clang/test/CXX/drs/cwg661.cpp @@ -6,9 +6,9 @@ // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -namespace dr661 { +namespace cwg661 { -void f(int a, int b) { // dr661: 2.7 +void f(int a, int b) { // cwg661: 2.7 a == b; a != b; a < b; @@ -17,9 +17,9 @@ void f(int a, int b) { // dr661: 2.7 a >= b; } -} // namespace dr661 +} // namespace cwg661 -// CHECK-LABEL: define {{.*}} void @dr661::f(int, int) +// CHECK-LABEL: define {{.*}} void @cwg661::f(int, int) // CHECK: icmp eq // CHECK: icmp ne // CHECK: icmp slt diff --git a/clang/test/CXX/drs/dr672.cpp b/clang/test/CXX/drs/cwg672.cpp similarity index 91% rename from clang/test/CXX/drs/dr672.cpp rename to clang/test/CXX/drs/cwg672.cpp index d5f0530ecbc9dda73e223587ae879b3918c96dc8..07a64eaaf82698d7e8c9a992b7d4dbe42177efb5 100644 --- a/clang/test/CXX/drs/dr672.cpp +++ b/clang/test/CXX/drs/cwg672.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr672 { // dr672: 2.7 +namespace cwg672 { // cwg672: 2.7 struct A { A() NOTHROW; @@ -22,11 +22,11 @@ void f() { A *a = new A; } -} // namespace dr672 +} // namespace cwg672 -// CHECK-LABEL: define {{.*}} void @dr672::f()() +// CHECK-LABEL: define {{.*}} void @cwg672::f()() // CHECK: [[A:%.+]] = alloca ptr // CHECK: [[CALL:%.+]] = call {{.*}} ptr @operator new(unsigned long) -// CHECK: call void @dr672::A::A() +// CHECK: call void @cwg672::A::A() // CHECK: store ptr [[CALL]], ptr [[A]] // CHECK-LABEL: } diff --git a/clang/test/CXX/drs/dr593.cpp b/clang/test/CXX/drs/cwgr593.cpp similarity index 93% rename from clang/test/CXX/drs/dr593.cpp rename to clang/test/CXX/drs/cwgr593.cpp index 4998af966ebb902d7375b4e18dea88f9d9842d54..d747f4e4a16179a8e1d422dbabab2c1ec4d188b0 100644 --- a/clang/test/CXX/drs/dr593.cpp +++ b/clang/test/CXX/drs/cwgr593.cpp @@ -12,7 +12,7 @@ #define NOTHROW noexcept(true) #endif -namespace dr593 { // dr593: 2.8 +namespace cwg593 { // cwg593: 2.8 void f(); void fence() NOTHROW; @@ -29,7 +29,7 @@ void g() { A(); } -} // namespace dr593 +} // namespace cwg593 -// CHECK: call void @dr593::fence()() +// CHECK: call void @cwg593::fence()() // CHECK-NEXT: invoke void @__cxa_rethrow() diff --git a/clang/test/CXX/drs/dr0xx.cpp b/clang/test/CXX/drs/dr0xx.cpp index 5959f0a0c8dd6501b0e009aeb1cff0b2b7afdca1..a304862885c6403ad670f69c2c3025a08a5d7a6e 100644 --- a/clang/test/CXX/drs/dr0xx.cpp +++ b/clang/test/CXX/drs/dr0xx.cpp @@ -5,44 +5,44 @@ // RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple -namespace dr1 { // dr1: no - namespace X { extern "C" void dr1_f(int a = 1); } - namespace Y { extern "C" void dr1_f(int a = 1); } - using X::dr1_f; using Y::dr1_f; +namespace cwg1 { // cwg1: no + namespace X { extern "C" void cwg1_f(int a = 1); } + namespace Y { extern "C" void cwg1_f(int a = 1); } + using X::cwg1_f; using Y::cwg1_f; void g() { - dr1_f(0); + cwg1_f(0); // FIXME: This should be rejected, due to the ambiguous default argument. - dr1_f(); + cwg1_f(); } namespace X { - using Y::dr1_f; + using Y::cwg1_f; void h() { - dr1_f(0); + cwg1_f(0); // FIXME: This should be rejected, due to the ambiguous default argument. - dr1_f(); + cwg1_f(); } } namespace X { void z(int); } - void X::z(int = 1) {} // #dr1-z + void X::z(int = 1) {} // #cwg1-z namespace X { void z(int = 1); // expected-error@-1 {{redefinition of default argument}} - // expected-note@#dr1-z {{previous definition is here}} + // expected-note@#cwg1-z {{previous definition is here}} } void i(int = 1); void j() { void i(int = 1); - using dr1::i; + using cwg1::i; i(0); // FIXME: This should be rejected, due to the ambiguous default argument. i(); } void k() { - using dr1::i; + using cwg1::i; void i(int = 1); i(0); // FIXME: This should be rejected, due to the ambiguous default argument. @@ -50,27 +50,27 @@ namespace dr1 { // dr1: no } } -namespace dr3 { // dr3: yes +namespace cwg3 { // cwg3: yes template struct A {}; - template void f(T) { A a; } // #dr3-f-T + template void f(T) { A a; } // #cwg3-f-T template void f(int); template<> struct A {}; - // expected-error@-1 {{explicit specialization of 'dr3::A' after instantiation}} - // expected-note@#dr3-f-T {{implicit instantiation first required here}} + // expected-error@-1 {{explicit specialization of 'cwg3::A' after instantiation}} + // expected-note@#cwg3-f-T {{implicit instantiation first required here}} } -namespace dr4 { // dr4: 2.8 +namespace cwg4 { // cwg4: 2.8 extern "C" { - static void dr4_f(int) {} - static void dr4_f(float) {} - void dr4_g(int) {} // #dr4-g-int - void dr4_g(float) {} - // expected-error@-1 {{conflicting types for 'dr4_g'}} - // expected-note@#dr4-g-int {{previous definition is here}} + static void cwg4_f(int) {} + static void cwg4_f(float) {} + void cwg4_g(int) {} // #cwg4-g-int + void cwg4_g(float) {} + // expected-error@-1 {{conflicting types for 'cwg4_g'}} + // expected-note@#cwg4-g-int {{previous definition is here}} } } -namespace dr5 { // dr5: 3.1 +namespace cwg5 { // cwg5: 3.1 struct A {} a; struct B { B(const A&); @@ -84,24 +84,24 @@ namespace dr5 { // dr5: 3.1 const C c = e; } -namespace dr7 { // dr7: 3.4 +namespace cwg7 { // cwg7: 3.4 class A { public: ~A(); }; - class B : virtual private A {}; // #dr7-B - class C : public B {} c; // #dr7-C - // expected-error@#dr7-C {{inherited virtual base class 'A' has private destructor}} - // expected-note@#dr7-C {{in implicit default constructor for 'dr7::C' first required here}} - // expected-note@#dr7-B {{declared private here}} - // expected-error@#dr7-C {{inherited virtual base class 'A' has private destructor}} - // expected-note@#dr7-C {{in implicit destructor for 'dr7::C' first required here}} - // expected-note@#dr7-B {{declared private here}} + class B : virtual private A {}; // #cwg7-B + class C : public B {} c; // #cwg7-C + // expected-error@#cwg7-C {{inherited virtual base class 'A' has private destructor}} + // expected-note@#cwg7-C {{in implicit default constructor for 'cwg7::C' first required here}} + // expected-note@#cwg7-B {{declared private here}} + // expected-error@#cwg7-C {{inherited virtual base class 'A' has private destructor}} + // expected-note@#cwg7-C {{in implicit destructor for 'cwg7::C' first required here}} + // expected-note@#cwg7-B {{declared private here}} class VeryDerivedC : public B, virtual public A {} vdc; - class X { ~X(); }; // #dr7-X + class X { ~X(); }; // #cwg7-X class Y : X { ~Y() {} }; // expected-error@-1 {{base class 'X' has private destructor}} - // expected-note@#dr7-X {{implicitly declared private here}} + // expected-note@#cwg7-X {{implicitly declared private here}} - namespace PR16370 { // This regressed the first time DR7 was fixed. + namespace PR16370 { // This regressed the first time CWG7 was fixed. struct S1 { virtual ~S1(); }; struct S2 : S1 {}; struct S3 : S2 {}; @@ -114,7 +114,7 @@ namespace dr7 { // dr7: 3.4 } } -namespace dr8 { // dr8: dup 45 +namespace cwg8 { // cwg8: dup 45 class A { struct U; static const int k = 5; @@ -126,23 +126,23 @@ namespace dr8 { // dr8: dup 45 A::T *A::g() { return 0; } } -namespace dr9 { // dr9: 2.8 +namespace cwg9 { // cwg9: 2.8 struct B { protected: - int m; // #dr9-m + int m; // #cwg9-m friend int R1(); }; - struct N : protected B { // #dr9-N + struct N : protected B { // #cwg9-N friend int R2(); } n; int R1() { return n.m; } - // expected-error@-1 {{'m' is a protected member of 'dr9::B'}} - // expected-note@#dr9-N {{constrained by protected inheritance here}} - // expected-note@#dr9-m {{member is declared here}} + // expected-error@-1 {{'m' is a protected member of 'cwg9::B'}} + // expected-note@#cwg9-N {{constrained by protected inheritance here}} + // expected-note@#cwg9-m {{member is declared here}} int R2() { return n.m; } } -namespace dr10 { // dr10: dup 45 +namespace cwg10 { // cwg10: dup 45 class A { struct B { A::B *p; @@ -150,7 +150,7 @@ namespace dr10 { // dr10: dup 45 }; } -namespace dr11 { // dr11: yes +namespace cwg11 { // cwg11: yes template struct A : T { using typename T::U; U u; @@ -164,19 +164,19 @@ namespace dr11 { // dr11: yes A ax; } -namespace dr12 { // dr12: sup 239 +namespace cwg12 { // cwg12: sup 239 enum E { e }; E &f(E, E = e); void g() { int &f(int, E = e); - // Under DR12, these call two different functions. - // Under DR239, they call the same function. + // Under CWG12, these call two different functions. + // Under CWG239, they call the same function. int &b = f(e); int &c = f(1); } } -namespace dr13 { // dr13: no +namespace cwg13 { // cwg13: no extern "C" void f(int); void g(char); @@ -191,60 +191,60 @@ namespace dr13 { // dr13: no int a4 = h(g); } -namespace dr14 { // dr14: 3.4 - namespace X { extern "C" int dr14_f(); } - namespace Y { extern "C" int dr14_f(); } +namespace cwg14 { // cwg14: 3.4 + namespace X { extern "C" int cwg14_f(); } + namespace Y { extern "C" int cwg14_f(); } using namespace X; using namespace Y; - int k = dr14_f(); + int k = cwg14_f(); class C { int k; - friend int Y::dr14_f(); + friend int Y::cwg14_f(); } c; namespace Z { - extern "C" int dr14_f() { return c.k; } + extern "C" int cwg14_f() { return c.k; } } - namespace X { typedef int T; typedef int U; } // #dr14-X-U - namespace Y { typedef int T; typedef long U; } // #dr14-Y-U + namespace X { typedef int T; typedef int U; } // #cwg14-X-U + namespace Y { typedef int T; typedef long U; } // #cwg14-Y-U T t; // ok, same type both times U u; // expected-error@-1 {{reference to 'U' is ambiguous}} - // expected-note@#dr14-X-U {{candidate found by name lookup is 'dr14::X::U'}} - // expected-note@#dr14-Y-U {{candidate found by name lookup is 'dr14::Y::U'}} + // expected-note@#cwg14-X-U {{candidate found by name lookup is 'cwg14::X::U'}} + // expected-note@#cwg14-Y-U {{candidate found by name lookup is 'cwg14::Y::U'}} } -namespace dr15 { // dr15: yes - template void f(int); // #dr15-f-decl-first +namespace cwg15 { // cwg15: yes + template void f(int); // #cwg15-f-decl-first template void f(int = 0); // expected-error@-1 {{default arguments cannot be added to a function template that has already been declared}} - // expected-note@#dr15-f-decl-first {{previous template declaration is here}} + // expected-note@#cwg15-f-decl-first {{previous template declaration is here}} } -namespace dr16 { // dr16: 2.8 - class A { // #dr16-A - void f(); // #dr16-A-f-decl +namespace cwg16 { // cwg16: 2.8 + class A { // #cwg16-A + void f(); // #cwg16-A-f-decl friend class C; }; - class B : A {}; // #dr16-B + class B : A {}; // #cwg16-B class C : B { void g() { f(); - // expected-error@-1 {{'f' is a private member of 'dr16::A'}} - // expected-note@#dr16-B {{constrained by implicitly private inheritance here}} - // expected-note@#dr16-A-f-decl {{member is declared here}} - A::f(); // #dr16-A-f-call - // expected-error@#dr16-A-f-call {{'A' is a private member of 'dr16::A'}} - // expected-note@#dr16-B {{constrained by implicitly private inheritance here}} - // expected-note@#dr16-A {{member is declared here}} - // expected-error@#dr16-A-f-call {{cannot cast 'dr16::C' to its private base class 'dr16::A'}} - // expected-note@#dr16-B {{implicitly declared private here}} + // expected-error@-1 {{'f' is a private member of 'cwg16::A'}} + // expected-note@#cwg16-B {{constrained by implicitly private inheritance here}} + // expected-note@#cwg16-A-f-decl {{member is declared here}} + A::f(); // #cwg16-A-f-call + // expected-error@#cwg16-A-f-call {{'A' is a private member of 'cwg16::A'}} + // expected-note@#cwg16-B {{constrained by implicitly private inheritance here}} + // expected-note@#cwg16-A {{member is declared here}} + // expected-error@#cwg16-A-f-call {{cannot cast 'cwg16::C' to its private base class 'cwg16::A'}} + // expected-note@#cwg16-B {{implicitly declared private here}} } }; } -namespace dr17 { // dr17: yes +namespace cwg17 { // cwg17: yes class A { int n; int f(); @@ -257,38 +257,38 @@ namespace dr17 { // dr17: yes }; } -// dr18: sup 577 +// cwg18: sup 577 -namespace dr19 { // dr19: 3.1 +namespace cwg19 { // cwg19: 3.1 struct A { - int n; // #dr19-n + int n; // #cwg19-n }; - struct B : protected A { // #dr19-B + struct B : protected A { // #cwg19-B }; struct C : B {} c; struct D : B { int get1() { return c.n; } - // expected-error@-1 {{'n' is a protected member of 'dr19::A'}} - // expected-note@#dr19-B {{constrained by protected inheritance here}} - // expected-note@#dr19-n {{member is declared here}} + // expected-error@-1 {{'n' is a protected member of 'cwg19::A'}} + // expected-note@#cwg19-B {{constrained by protected inheritance here}} + // expected-note@#cwg19-n {{member is declared here}} int get2() { return ((A&)c).n; } // ok, A is an accessible base of B from here }; } -namespace dr20 { // dr20: 2.8 +namespace cwg20 { // cwg20: 2.8 class X { public: X(); private: - X(const X&); // #dr20-X-ctor + X(const X&); // #cwg20-X-ctor }; X &f(); X x = f(); - // expected-error@-1 {{calling a private constructor of class 'dr20::X'}} - // expected-note@#dr20-X-ctor {{declared private here}} + // expected-error@-1 {{calling a private constructor of class 'cwg20::X'}} + // expected-note@#cwg20-X-ctor {{declared private here}} } -namespace dr21 { // dr21: 3.4 +namespace cwg21 { // cwg21: 3.4 template struct A; struct X { template friend struct A; @@ -298,25 +298,25 @@ namespace dr21 { // dr21: 3.4 }; } -namespace dr22 { // dr22: sup 481 - template struct X; - // expected-error@-1 {{unknown type name 'dr22_T'}} +namespace cwg22 { // cwg22: sup 481 + template struct X; + // expected-error@-1 {{unknown type name 'cwg22_T'}} typedef int T; template struct Y; } -namespace dr23 { // dr23: yes - template void f(T, T); // #dr23-f-T-T - template void f(T, int); // #dr23-f-T-int +namespace cwg23 { // cwg23: yes + template void f(T, T); // #cwg23-f-T-T + template void f(T, int); // #cwg23-f-T-int void g() { f(0, 0); } // expected-error@-1 {{call to 'f' is ambiguous}} - // expected-note@#dr23-f-T-T {{candidate function [with T = int]}} - // expected-note@#dr23-f-T-int {{candidate function [with T = int]}} + // expected-note@#cwg23-f-T-T {{candidate function [with T = int]}} + // expected-note@#cwg23-f-T-int {{candidate function [with T = int]}} } -// dr24: na +// cwg24: na -namespace dr25 { // dr25: yes +namespace cwg25 { // cwg25: yes struct A { void f() throw(int); // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} @@ -351,7 +351,7 @@ namespace dr25 { // dr25: yes } } -namespace dr26 { // dr26: yes +namespace cwg26 { // cwg26: yes struct A { A(A, const A & = A()); }; // expected-error@-1 {{copy constructor must pass its first argument by reference}} struct B { @@ -371,77 +371,77 @@ namespace dr26 { // dr26: yes }; } -namespace dr27 { // dr27: yes +namespace cwg27 { // cwg27: yes enum E { e } n; E &m = true ? n : n; } -// dr28: na lib +// cwg28: na lib -namespace dr29 { // dr29: 3.4 - void dr29_f0(); // #dr29-f0 - void g0() { void dr29_f0(); } - extern "C++" void g0_cxx() { void dr29_f0(); } - extern "C" void g0_c() { void dr29_f0(); } - // expected-error@-1 {{declaration of 'dr29_f0' has a different language linkage}} - // expected-note@#dr29-f0 {{previous declaration is here}} +namespace cwg29 { // cwg29: 3.4 + void cwg29_f0(); // #cwg29-f0 + void g0() { void cwg29_f0(); } + extern "C++" void g0_cxx() { void cwg29_f0(); } + extern "C" void g0_c() { void cwg29_f0(); } + // expected-error@-1 {{declaration of 'cwg29_f0' has a different language linkage}} + // expected-note@#cwg29-f0 {{previous declaration is here}} - extern "C" void dr29_f1(); // #dr29-f1 - void g1() { void dr29_f1(); } - extern "C" void g1_c() { void dr29_f1(); } - extern "C++" void g1_cxx() { void dr29_f1(); } - // expected-error@-1 {{declaration of 'dr29_f1' has a different language linkage}} - // expected-note@#dr29-f1 {{previous declaration is here}} + extern "C" void cwg29_f1(); // #cwg29-f1 + void g1() { void cwg29_f1(); } + extern "C" void g1_c() { void cwg29_f1(); } + extern "C++" void g1_cxx() { void cwg29_f1(); } + // expected-error@-1 {{declaration of 'cwg29_f1' has a different language linkage}} + // expected-note@#cwg29-f1 {{previous declaration is here}} - void g2() { void dr29_f2(); } // #dr29-f2 - extern "C" void dr29_f2(); - // expected-error@-1 {{declaration of 'dr29_f2' has a different language linkage}} - // expected-note@#dr29-f2 {{previous declaration is here}} + void g2() { void cwg29_f2(); } // #cwg29-f2 + extern "C" void cwg29_f2(); + // expected-error@-1 {{declaration of 'cwg29_f2' has a different language linkage}} + // expected-note@#cwg29-f2 {{previous declaration is here}} - extern "C" void g3() { void dr29_f3(); } // #dr29-f3 - extern "C++" void dr29_f3(); - // expected-error@-1 {{declaration of 'dr29_f3' has a different language linkage}} - // expected-note@#dr29-f3 {{previous declaration is here}} + extern "C" void g3() { void cwg29_f3(); } // #cwg29-f3 + extern "C++" void cwg29_f3(); + // expected-error@-1 {{declaration of 'cwg29_f3' has a different language linkage}} + // expected-note@#cwg29-f3 {{previous declaration is here}} - extern "C++" void g4() { void dr29_f4(); } // #dr29-f4 - extern "C" void dr29_f4(); - // expected-error@-1 {{declaration of 'dr29_f4' has a different language linkage}} - // expected-note@#dr29-f4 {{previous declaration is here}} + extern "C++" void g4() { void cwg29_f4(); } // #cwg29-f4 + extern "C" void cwg29_f4(); + // expected-error@-1 {{declaration of 'cwg29_f4' has a different language linkage}} + // expected-note@#cwg29-f4 {{previous declaration is here}} extern "C" void g5(); - extern "C++" void dr29_f5(); + extern "C++" void cwg29_f5(); void g5() { - void dr29_f5(); // ok, g5 is extern "C" but we're not inside the linkage-specification here. + void cwg29_f5(); // ok, g5 is extern "C" but we're not inside the linkage-specification here. } extern "C++" void g6(); - extern "C" void dr29_f6(); + extern "C" void cwg29_f6(); void g6() { - void dr29_f6(); // ok, g6 is extern "C" but we're not inside the linkage-specification here. + void cwg29_f6(); // ok, g6 is extern "C" but we're not inside the linkage-specification here. } extern "C" void g7(); - extern "C++" void dr29_f7(); // #dr29-f7 + extern "C++" void cwg29_f7(); // #cwg29-f7 extern "C" void g7() { - void dr29_f7(); - // expected-error@-1 {{declaration of 'dr29_f7' has a different language linkage}} - // expected-note@#dr29-f7 {{previous declaration is here}} + void cwg29_f7(); + // expected-error@-1 {{declaration of 'cwg29_f7' has a different language linkage}} + // expected-note@#cwg29-f7 {{previous declaration is here}} } extern "C++" void g8(); - extern "C" void dr29_f8(); // #dr29-f8 + extern "C" void cwg29_f8(); // #cwg29-f8 extern "C++" void g8() { - void dr29_f8(); - // expected-error@-1 {{declaration of 'dr29_f8' has a different language linkage}} - // expected-note@#dr29-f8 {{previous declaration is here}} + void cwg29_f8(); + // expected-error@-1 {{declaration of 'cwg29_f8' has a different language linkage}} + // expected-note@#cwg29-f8 {{previous declaration is here}} } } -namespace dr30 { // dr30: sup 468 c++11 +namespace cwg30 { // cwg30: sup 468 c++11 struct A { template static int f(); } a, *p = &a; - // FIXME: It's not clear whether DR468 applies to C++98 too. + // FIXME: It's not clear whether CWG468 applies to C++98 too. int x = A::template f<0>(); // cxx98-error@-1 {{'template' keyword outside of a template}} int y = a.template f<0>(); @@ -450,29 +450,29 @@ namespace dr30 { // dr30: sup 468 c++11 // cxx98-error@-1 {{'template' keyword outside of a template}} } -namespace dr31 { // dr31: 2.8 +namespace cwg31 { // cwg31: 2.8 class X { private: - void operator delete(void*); // #dr31-delete + void operator delete(void*); // #cwg31-delete }; // We would call X::operator delete if X() threw (even though it can't, // and even though we allocated the X using ::operator delete). X *p = new X; - // expected-error@-1 {{'operator delete' is a private member of 'dr31::X'}} - // expected-note@#dr31-delete {{declared private here}} + // expected-error@-1 {{'operator delete' is a private member of 'cwg31::X'}} + // expected-note@#cwg31-delete {{declared private here}} } -// dr32: na +// cwg32: na -namespace dr33 { // dr33: 9 - namespace X { struct S; void f(void (*)(S)); } // #dr33-f-S - namespace Y { struct T; void f(void (*)(T)); } // #dr33-f-T +namespace cwg33 { // cwg33: 9 + namespace X { struct S; void f(void (*)(S)); } // #cwg33-f-S + namespace Y { struct T; void f(void (*)(T)); } // #cwg33-f-T void g(X::S); template Z g(Y::T); void h() { f(&g); } // expected-error@-1 {{call to 'f' is ambiguous}} - // expected-note@#dr33-f-S {{candidate function}} - // expected-note@#dr33-f-T {{candidate function}} + // expected-note@#cwg33-f-S {{candidate function}} + // expected-note@#cwg33-f-T {{candidate function}} template void t(X::S); template void u(X::S); @@ -507,10 +507,10 @@ namespace dr33 { // dr33: 9 } } -// dr34: na -// dr35: dup 178 +// cwg34: na +// cwg35: dup 178 -namespace dr36 { // dr36: 2.8 +namespace cwg36 { // cwg36: 2.8 namespace example1 { namespace A { int i; @@ -540,25 +540,25 @@ namespace example2 { struct D : virtual B, virtual C { - using B::i; // #dr36-ex2-B-i-first + using B::i; // #cwg36-ex2-B-i-first using B::i; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex2-B-i-first {{previous using declaration}} + // expected-note@#cwg36-ex2-B-i-first {{previous using declaration}} - using C::i; // #dr36-ex2-C-i-first + using C::i; // #cwg36-ex2-C-i-first using C::i; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex2-C-i-first {{previous using declaration}} + // expected-note@#cwg36-ex2-C-i-first {{previous using declaration}} - using B::j; // #dr36-ex2-B-j-first + using B::j; // #cwg36-ex2-B-j-first using B::j; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex2-B-j-first {{previous using declaration}} + // expected-note@#cwg36-ex2-B-j-first {{previous using declaration}} - using C::j; // #dr36-ex2-C-j-first + using C::j; // #cwg36-ex2-C-j-first using C::j; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex2-C-j-first {{previous using declaration}} + // expected-note@#cwg36-ex2-C-j-first {{previous using declaration}} }; } @@ -578,25 +578,25 @@ namespace example3 { template struct D : virtual B, virtual C { - using B::i; // #dr36-ex3-B-i-first + using B::i; // #cwg36-ex3-B-i-first using B::i; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex3-B-i-first {{previous using declaration}} + // expected-note@#cwg36-ex3-B-i-first {{previous using declaration}} - using C::i; // #dr36-ex3-C-i-first + using C::i; // #cwg36-ex3-C-i-first using C::i; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex3-C-i-first {{previous using declaration}} + // expected-note@#cwg36-ex3-C-i-first {{previous using declaration}} - using B::j; // #dr36-ex3-B-j-first + using B::j; // #cwg36-ex3-B-j-first using B::j; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex3-B-j-first {{previous using declaration}} + // expected-note@#cwg36-ex3-B-j-first {{previous using declaration}} - using C::j; // #dr36-ex3-C-j-first + using C::j; // #cwg36-ex3-C-j-first using C::j; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-ex3-C-j-first {{previous using declaration}} + // expected-note@#cwg36-ex3-C-j-first {{previous using declaration}} }; } namespace example4 { @@ -607,23 +607,23 @@ namespace example4 { template struct G : E { - using E::k; // #dr36-E-k-first + using E::k; // #cwg36-E-k-first using E::k; // expected-error@-1 {{redeclaration of using declaration}} - // expected-note@#dr36-E-k-first {{previous using declaration}} + // expected-note@#cwg36-E-k-first {{previous using declaration}} }; } } -// dr37: sup 475 +// cwg37: sup 475 -namespace dr38 { // dr38: yes +namespace cwg38 { // cwg38: yes template struct X {}; template X operator+(X a, X b) { return a; } template X operator+(X, X); } -namespace dr39 { // dr39: no +namespace cwg39 { // cwg39: no namespace example1 { struct A { int &f(int); }; struct B : A { @@ -635,16 +635,16 @@ namespace dr39 { // dr39: no namespace example2 { struct A { - int &x(int); // #dr39-A-x-decl - static int &y(int); // #dr39-A-y-decl + int &x(int); // #cwg39-A-x-decl + static int &y(int); // #cwg39-A-y-decl }; struct V { int &z(int); }; struct B : A, virtual V { - using A::x; // #dr39-using-A-x + using A::x; // #cwg39-using-A-x float &x(float); - using A::y; // #dr39-using-A-y + using A::y; // #cwg39-using-A-y static float &y(float); using V::z; float &z(float); @@ -652,18 +652,18 @@ namespace dr39 { // dr39: no struct C : A, B, virtual V {} c; /* expected-warning@-1 {{direct base 'A' is inaccessible due to ambiguity: - struct dr39::example2::C -> A - struct dr39::example2::C -> B -> A}} */ + struct cwg39::example2::C -> A + struct cwg39::example2::C -> B -> A}} */ int &x = c.x(0); // expected-error@-1 {{member 'x' found in multiple base classes of different types}} - // expected-note@#dr39-A-x-decl {{member found by ambiguous name lookup}} - // expected-note@#dr39-using-A-x {{member found by ambiguous name lookup}} + // expected-note@#cwg39-A-x-decl {{member found by ambiguous name lookup}} + // expected-note@#cwg39-using-A-x {{member found by ambiguous name lookup}} // FIXME: This is valid, because we find the same static data member either way. int &y = c.y(0); // expected-error@-1 {{member 'y' found in multiple base classes of different types}} - // expected-note@#dr39-A-y-decl {{member found by ambiguous name lookup}} - // expected-note@#dr39-using-A-y {{member found by ambiguous name lookup}} + // expected-note@#cwg39-A-y-decl {{member found by ambiguous name lookup}} + // expected-note@#cwg39-using-A-y {{member found by ambiguous name lookup}} int &z = c.z(0); } @@ -676,63 +676,63 @@ namespace dr39 { // dr39: no } namespace example4 { - struct A { int n; }; // #dr39-ex4-A-n + struct A { int n; }; // #cwg39-ex4-A-n struct B : A {}; struct C : A {}; struct D : B, C { int f() { return n; } }; /* expected-error@-1 {{non-static member 'n' found in multiple base-class subobjects of type 'A': - struct dr39::example4::D -> B -> A - struct dr39::example4::D -> C -> A}} */ - // expected-note@#dr39-ex4-A-n {{member found by ambiguous name lookup}} + struct cwg39::example4::D -> B -> A + struct cwg39::example4::D -> C -> A}} */ + // expected-note@#cwg39-ex4-A-n {{member found by ambiguous name lookup}} } namespace PR5916 { // FIXME: This is valid. - struct A { int n; }; // #dr39-A-n + struct A { int n; }; // #cwg39-A-n struct B : A {}; struct C : A {}; struct D : B, C {}; - int k = sizeof(D::n); // #dr39-sizeof - /* expected-error@#dr39-sizeof + int k = sizeof(D::n); // #cwg39-sizeof + /* expected-error@#cwg39-sizeof {{non-static member 'n' found in multiple base-class subobjects of type 'A': - struct dr39::PR5916::D -> B -> A - struct dr39::PR5916::D -> C -> A}} */ - // expected-note@#dr39-A-n {{member found by ambiguous name lookup}} + struct cwg39::PR5916::D -> B -> A + struct cwg39::PR5916::D -> C -> A}} */ + // expected-note@#cwg39-A-n {{member found by ambiguous name lookup}} - // expected-error@#dr39-sizeof {{unknown type name}} + // expected-error@#cwg39-sizeof {{unknown type name}} #if __cplusplus >= 201103L decltype(D::n) n; /* expected-error@-1 {{non-static member 'n' found in multiple base-class subobjects of type 'A': - struct dr39::PR5916::D -> B -> A - struct dr39::PR5916::D -> C -> A}} */ - // expected-note@#dr39-A-n {{member found by ambiguous name lookup}} + struct cwg39::PR5916::D -> B -> A + struct cwg39::PR5916::D -> C -> A}} */ + // expected-note@#cwg39-A-n {{member found by ambiguous name lookup}} #endif } } -// dr40: na +// cwg40: na -namespace dr41 { // dr41: yes +namespace cwg41 { // cwg41: yes struct S f(S); } -namespace dr42 { // dr42: yes +namespace cwg42 { // cwg42: yes struct A { static const int k = 0; }; struct B : A { static const int k = A::k; }; } -// dr43: na +// cwg43: na -namespace dr44 { // dr44: sup 727 +namespace cwg44 { // cwg44: sup 727 struct A { template void f(); template<> void f<0>(); }; } -namespace dr45 { // dr45: yes +namespace cwg45 { // cwg45: yes class A { class B {}; class C : B {}; @@ -740,27 +740,27 @@ namespace dr45 { // dr45: yes }; } -namespace dr46 { // dr46: yes +namespace cwg46 { // cwg46: yes template struct A { template struct B {}; }; template template struct A::B; // expected-error@-1 {{expected unqualified-id}} } -namespace dr47 { // dr47: sup 329 +namespace cwg47 { // cwg47: sup 329 template struct A { - friend void f() { T t; } // #dr47-f + friend void f() { T t; } // #cwg47-f // expected-error@-1 {{redefinition of 'f'}} - // expected-note@#dr47-b {{in instantiation of template class 'dr47::A' requested here}} - // expected-note@#dr47-f {{previous definition is here}} + // expected-note@#cwg47-b {{in instantiation of template class 'cwg47::A' requested here}} + // expected-note@#cwg47-f {{previous definition is here}} }; A a; - A b; // #dr47-b + A b; // #cwg47-b void f(); void g() { f(); } } -namespace dr48 { // dr48: yes +namespace cwg48 { // cwg48: yes namespace { struct S { static const int m = 0; @@ -776,45 +776,45 @@ namespace dr48 { // dr48: yes const int &c = S::o; } -namespace dr49 { // dr49: 2.8 - template struct A {}; // #dr49-A +namespace cwg49 { // cwg49: 2.8 + template struct A {}; // #cwg49-A int k; #if __has_feature(cxx_constexpr) constexpr #endif - int *const p = &k; // #dr49-p + int *const p = &k; // #cwg49-p A<&k> a; - A

b; // #dr49-b - // cxx98-error@#dr49-b {{non-type template argument referring to object 'p' with internal linkage is a C++11 extension}} - // cxx98-note@#dr49-p {{non-type template argument refers to object here}} - // cxx98-14-error@#dr49-b {{non-type template argument for template parameter of pointer type 'int *' must have its address taken}} - // cxx98-14-note@#dr49-A {{template parameter is declared here}} - int *q = &k; // #dr49-q - A c; // #dr49-c - // cxx98-error@#dr49-c {{non-type template argument for template parameter of pointer type 'int *' must have its address taken}} - // cxx98-note@#dr49-A {{template parameter is declared here}} - // cxx11-14-error@#dr49-c {{non-type template argument of type 'int *' is not a constant expression}} - // cxx11-14-note@#dr49-c {{read of non-constexpr variable 'q' is not allowed in a constant expression}} - // cxx11-14-note@#dr49-q {{declared here}} - // cxx11-14-note@#dr49-A {{template parameter is declared here}} - // since-cxx17-error@#dr49-c {{non-type template argument is not a constant expression}} - // since-cxx17-note@#dr49-c {{read of non-constexpr variable 'q' is not allowed in a constant expression}} - // since-cxx17-note@#dr49-q {{declared here}} -} - -namespace dr50 { // dr50: yes - struct X; // #dr50-X + A

b; // #cwg49-b + // cxx98-error@#cwg49-b {{non-type template argument referring to object 'p' with internal linkage is a C++11 extension}} + // cxx98-note@#cwg49-p {{non-type template argument refers to object here}} + // cxx98-14-error@#cwg49-b {{non-type template argument for template parameter of pointer type 'int *' must have its address taken}} + // cxx98-14-note@#cwg49-A {{template parameter is declared here}} + int *q = &k; // #cwg49-q + A c; // #cwg49-c + // cxx98-error@#cwg49-c {{non-type template argument for template parameter of pointer type 'int *' must have its address taken}} + // cxx98-note@#cwg49-A {{template parameter is declared here}} + // cxx11-14-error@#cwg49-c {{non-type template argument of type 'int *' is not a constant expression}} + // cxx11-14-note@#cwg49-c {{read of non-constexpr variable 'q' is not allowed in a constant expression}} + // cxx11-14-note@#cwg49-q {{declared here}} + // cxx11-14-note@#cwg49-A {{template parameter is declared here}} + // since-cxx17-error@#cwg49-c {{non-type template argument is not a constant expression}} + // since-cxx17-note@#cwg49-c {{read of non-constexpr variable 'q' is not allowed in a constant expression}} + // since-cxx17-note@#cwg49-q {{declared here}} +} + +namespace cwg50 { // cwg50: yes + struct X; // #cwg50-X extern X *p; X *q = (X*)p; X *r = static_cast(p); X *s = const_cast(p); X *t = reinterpret_cast(p); X *u = dynamic_cast(p); - // expected-error@-1 {{'dr50::X' is an incomplete type}} - // expected-note@#dr50-X {{forward declaration of 'dr50::X'}} + // expected-error@-1 {{'cwg50::X' is an incomplete type}} + // expected-note@#cwg50-X {{forward declaration of 'cwg50::X'}} } -namespace dr51 { // dr51: 2.8 +namespace cwg51 { // cwg51: 2.8 struct A {}; struct B : A {}; struct S { @@ -824,57 +824,57 @@ namespace dr51 { // dr51: 2.8 A &a = s; } -namespace dr52 { // dr52: 2.8 - struct A { int n; }; // #dr52-A - struct B : private A {} b; // #dr52-B - int k = b.A::n; // #dr52-k +namespace cwg52 { // cwg52: 2.8 + struct A { int n; }; // #cwg52-A + struct B : private A {} b; // #cwg52-B + int k = b.A::n; // #cwg52-k // FIXME: This first diagnostic is very strangely worded, and seems to be bogus. - // expected-error@#dr52-k {{'A' is a private member of 'dr52::A'}} - // expected-note@#dr52-B {{constrained by private inheritance here}} - // expected-note@#dr52-A {{member is declared here}} - // expected-error@#dr52-k {{cannot cast 'struct B' to its private base class 'dr52::A'}} - // expected-note@#dr52-B {{declared private here}} + // expected-error@#cwg52-k {{'A' is a private member of 'cwg52::A'}} + // expected-note@#cwg52-B {{constrained by private inheritance here}} + // expected-note@#cwg52-A {{member is declared here}} + // expected-error@#cwg52-k {{cannot cast 'struct B' to its private base class 'cwg52::A'}} + // expected-note@#cwg52-B {{declared private here}} } -namespace dr53 { // dr53: yes +namespace cwg53 { // cwg53: yes int n = 0; enum E { e } x = static_cast(n); } -namespace dr54 { // dr54: 2.8 +namespace cwg54 { // cwg54: 2.8 struct A { int a; } a; struct V { int v; } v; - struct B : private A, virtual V { int b; } b; // #dr54-B + struct B : private A, virtual V { int b; } b; // #cwg54-B A &sab = static_cast(b); // expected-error@-1 {{cannot cast 'struct B' to its private base class 'A'}} - // expected-note@#dr54-B {{declared private here}} + // expected-note@#cwg54-B {{declared private here}} A *spab = static_cast(&b); // expected-error@-1 {{cannot cast 'struct B' to its private base class 'A'}} - // expected-note@#dr54-B {{declared private here}} + // expected-note@#cwg54-B {{declared private here}} int A::*smab = static_cast(&B::b); - // expected-error@-1 {{cannot cast 'dr54::B' to its private base class 'dr54::A'}} - // expected-note@#dr54-B {{declared private here}} + // expected-error@-1 {{cannot cast 'cwg54::B' to its private base class 'cwg54::A'}} + // expected-note@#cwg54-B {{declared private here}} B &sba = static_cast(a); - // expected-error@-1 {{cannot cast private base class 'dr54::A' to 'dr54::B'}} - // expected-note@#dr54-B {{declared private here}} + // expected-error@-1 {{cannot cast private base class 'cwg54::A' to 'cwg54::B'}} + // expected-note@#cwg54-B {{declared private here}} B *spba = static_cast(&a); - // expected-error@-1 {{cannot cast private base class 'dr54::A' to 'dr54::B'}} - // expected-note@#dr54-B {{declared private here}} + // expected-error@-1 {{cannot cast private base class 'cwg54::A' to 'cwg54::B'}} + // expected-note@#cwg54-B {{declared private here}} int B::*smba = static_cast(&A::a); - // expected-error@-1 {{cannot cast private base class 'dr54::A' to 'dr54::B'}} - // expected-note@#dr54-B {{declared private here}} + // expected-error@-1 {{cannot cast private base class 'cwg54::A' to 'cwg54::B'}} + // expected-note@#cwg54-B {{declared private here}} V &svb = static_cast(b); V *spvb = static_cast(&b); int V::*smvb = static_cast(&B::b); - // expected-error@-1 {{conversion from pointer to member of class 'dr54::B' to pointer to member of class 'dr54::V' via virtual base 'dr54::V' is not allowed}} + // expected-error@-1 {{conversion from pointer to member of class 'cwg54::B' to pointer to member of class 'cwg54::V' via virtual base 'cwg54::V' is not allowed}} B &sbv = static_cast(v); - // expected-error@-1 {{cannot cast 'struct V' to 'B &' via virtual base 'dr54::V'}} + // expected-error@-1 {{cannot cast 'struct V' to 'B &' via virtual base 'cwg54::V'}} B *spbv = static_cast(&v); - // expected-error@-1 {{cannot cast 'dr54::V *' to 'B *' via virtual base 'dr54::V'}} + // expected-error@-1 {{cannot cast 'cwg54::V *' to 'B *' via virtual base 'cwg54::V'}} int B::*smbv = static_cast(&V::v); - // expected-error@-1 {{conversion from pointer to member of class 'dr54::V' to pointer to member of class 'dr54::B' via virtual base 'dr54::V' is not allowed}} + // expected-error@-1 {{conversion from pointer to member of class 'cwg54::V' to pointer to member of class 'cwg54::B' via virtual base 'cwg54::V' is not allowed}} A &cab = (A&)(b); A *cpab = (A*)(&b); @@ -886,37 +886,37 @@ namespace dr54 { // dr54: 2.8 V &cvb = (V&)(b); V *cpvb = (V*)(&b); int V::*cmvb = (int V::*)(&B::b); - // expected-error@-1 {{conversion from pointer to member of class 'dr54::B' to pointer to member of class 'dr54::V' via virtual base 'dr54::V' is not allowed}} + // expected-error@-1 {{conversion from pointer to member of class 'cwg54::B' to pointer to member of class 'cwg54::V' via virtual base 'cwg54::V' is not allowed}} B &cbv = (B&)(v); - // expected-error@-1 {{cannot cast 'struct V' to 'B &' via virtual base 'dr54::V'}} + // expected-error@-1 {{cannot cast 'struct V' to 'B &' via virtual base 'cwg54::V'}} B *cpbv = (B*)(&v); - // expected-error@-1 {{cannot cast 'dr54::V *' to 'B *' via virtual base 'dr54::V'}} + // expected-error@-1 {{cannot cast 'cwg54::V *' to 'B *' via virtual base 'cwg54::V'}} int B::*cmbv = (int B::*)(&V::v); - // expected-error@-1 {{conversion from pointer to member of class 'dr54::V' to pointer to member of class 'dr54::B' via virtual base 'dr54::V' is not allowed}} + // expected-error@-1 {{conversion from pointer to member of class 'cwg54::V' to pointer to member of class 'cwg54::B' via virtual base 'cwg54::V' is not allowed}} } -namespace dr55 { // dr55: yes +namespace cwg55 { // cwg55: yes enum E { e = 5 }; int test[(e + 1 == 6) ? 1 : -1]; } -namespace dr56 { // dr56: yes +namespace cwg56 { // cwg56: yes struct A { - typedef int T; // #dr56-typedef-int-T-first + typedef int T; // #cwg56-typedef-int-T-first typedef int T; // expected-error@-1 {{redefinition of 'T'}} - // expected-note@#dr56-typedef-int-T-first {{previous definition is here}} + // expected-note@#cwg56-typedef-int-T-first {{previous definition is here}} }; struct B { struct X; - typedef X X; // #dr56-typedef-X-X-first + typedef X X; // #cwg56-typedef-X-X-first typedef X X; // expected-error@-1 {{redefinition of 'X'}} - // expected-note@#dr56-typedef-X-X-first {{previous definition is here}} + // expected-note@#cwg56-typedef-X-X-first {{previous definition is here}} }; } -namespace dr58 { // dr58: 3.1 +namespace cwg58 { // cwg58: 3.1 // FIXME: Ideally, we should have a CodeGen test for this. #if __cplusplus >= 201103L enum E1 { E1_0 = 0, E1_1 = 1 }; @@ -927,54 +927,54 @@ namespace dr58 { // dr58: 3.1 #endif } -namespace dr59 { // dr59: yes +namespace cwg59 { // cwg59: yes #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-volatile" template struct convert_to { operator T() const; }; - struct A {}; // #dr59-A - struct B : A {}; // #dr59-B + struct A {}; // #cwg59-A + struct B : A {}; // #cwg59-B A a1 = convert_to(); A a2 = convert_to(); A a3 = convert_to(); A a4 = convert_to(); - // cxx98-14-error@-1 {{no viable constructor copying variable of type 'const volatile dr59::A'}} - // cxx98-14-note@#dr59-A {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile dr59::A') would lose volatile qualifier}} - // cxx11-14-note@#dr59-A {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile dr59::A') would lose const and volatile qualifiers}} - // cxx98-14-note@#dr59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + // cxx98-14-error@-1 {{no viable constructor copying variable of type 'const volatile cwg59::A'}} + // cxx98-14-note@#cwg59-A {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile cwg59::A') would lose volatile qualifier}} + // cxx11-14-note@#cwg59-A {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile cwg59::A') would lose const and volatile qualifiers}} + // cxx98-14-note@#cwg59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} A a5 = convert_to(); - // expected-error@-1 {{no viable constructor copying variable of type 'const volatile dr59::A'}} - // expected-note@#dr59-A {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile dr59::A') would lose volatile qualifier}} - // since-cxx11-note@#dr59-A {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile dr59::A') would lose const and volatile qualifiers}} - // expected-note@#dr59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + // expected-error@-1 {{no viable constructor copying variable of type 'const volatile cwg59::A'}} + // expected-note@#cwg59-A {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile cwg59::A') would lose volatile qualifier}} + // since-cxx11-note@#cwg59-A {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile cwg59::A') would lose const and volatile qualifiers}} + // expected-note@#cwg59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} B b1 = convert_to(); B b2 = convert_to(); B b3 = convert_to(); B b4 = convert_to(); - // cxx98-14-error@-1 {{no viable constructor copying variable of type 'const volatile dr59::B'}} - // cxx98-14-note@#dr59-B {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile dr59::B') would lose volatile qualifier}} - // cxx11-14-note@#dr59-B {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile dr59::B') would lose const and volatile qualifiers}} - // cxx98-14-note@#dr59-B {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + // cxx98-14-error@-1 {{no viable constructor copying variable of type 'const volatile cwg59::B'}} + // cxx98-14-note@#cwg59-B {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile cwg59::B') would lose volatile qualifier}} + // cxx11-14-note@#cwg59-B {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile cwg59::B') would lose const and volatile qualifiers}} + // cxx98-14-note@#cwg59-B {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} B b5 = convert_to(); - // expected-error@-1 {{no viable constructor copying variable of type 'const volatile dr59::B'}} - // expected-note@#dr59-B {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile dr59::B') would lose volatile qualifier}} - // since-cxx11-note@#dr59-B {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile dr59::B') would lose const and volatile qualifiers}} - // expected-note@#dr59-B {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + // expected-error@-1 {{no viable constructor copying variable of type 'const volatile cwg59::B'}} + // expected-note@#cwg59-B {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('const volatile cwg59::B') would lose volatile qualifier}} + // since-cxx11-note@#cwg59-B {{candidate constructor (the implicit move constructor) not viable: 1st argument ('const volatile cwg59::B') would lose const and volatile qualifiers}} + // expected-note@#cwg59-B {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} A c1 = convert_to(); A c2 = convert_to(); A c3 = convert_to(); A c4 = convert_to(); - // expected-error@-1 {{no viable constructor copying variable of type 'const volatile dr59::B'}} - // expected-note@#dr59-A {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const volatile dr59::B' to 'const A &' for 1st argument}} - // since-cxx11-note@#dr59-A {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'const volatile dr59::B' to 'A &&' for 1st argument}} - // expected-note@#dr59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + // expected-error@-1 {{no viable constructor copying variable of type 'const volatile cwg59::B'}} + // expected-note@#cwg59-A {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const volatile cwg59::B' to 'const A &' for 1st argument}} + // since-cxx11-note@#cwg59-A {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'const volatile cwg59::B' to 'A &&' for 1st argument}} + // expected-note@#cwg59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} A c5 = convert_to(); - // expected-error@-1 {{no viable constructor copying variable of type 'const volatile dr59::B'}} - // expected-note@#dr59-A {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const volatile dr59::B' to 'const A &' for 1st argument}} - // since-cxx11-note@#dr59-A {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'const volatile dr59::B' to 'A &&' for 1st argument}} - // expected-note@#dr59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + // expected-error@-1 {{no viable constructor copying variable of type 'const volatile cwg59::B'}} + // expected-note@#cwg59-A {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const volatile cwg59::B' to 'const A &' for 1st argument}} + // since-cxx11-note@#cwg59-A {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'const volatile cwg59::B' to 'A &&' for 1st argument}} + // expected-note@#cwg59-A {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} int n1 = convert_to(); int n2 = convert_to(); @@ -984,14 +984,14 @@ namespace dr59 { // dr59: yes #pragma clang diagnostic pop } -namespace dr60 { // dr60: yes +namespace cwg60 { // cwg60: yes void f(int &); int &f(...); const int k = 0; int &n = f(k); } -namespace dr61 { // dr61: 3.4 +namespace cwg61 { // cwg61: 3.4 struct X { static void f(); } x; @@ -1008,7 +1008,7 @@ namespace dr61 { // dr61: 3.4 // expected-error@-1 {{cannot create a non-constant pointer to member function}} } -namespace dr62 { // dr62: 2.9 +namespace cwg62 { // cwg62: 2.9 struct A { struct { int n; } b; }; @@ -1019,7 +1019,7 @@ namespace dr62 { // dr62: 2.9 X x1; A a = get(); - typedef struct { } *NoNameForLinkagePtr; // #dr62-unnamed + typedef struct { } *NoNameForLinkagePtr; // #cwg62-unnamed NoNameForLinkagePtr noNameForLinkagePtr; struct Danger { @@ -1028,19 +1028,19 @@ namespace dr62 { // dr62: 2.9 X x2; // cxx98-error@-1 {{template argument uses unnamed type}} - // cxx98-note@#dr62-unnamed {{unnamed type used in template argument was declared here}} + // cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}} X x3; // cxx98-error@-1 {{template argument uses unnamed type}} - // cxx98-note@#dr62-unnamed {{unnamed type used in template argument was declared here}} + // cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}} NoNameForLinkagePtr p1 = get(); // cxx98-error@-1 {{template argument uses unnamed type}} - // cxx98-note@#dr62-unnamed {{unnamed type used in template argument was declared here}} + // cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}} NoNameForLinkagePtr p2 = get(); // cxx98-error@-1 {{template argument uses unnamed type}} - // cxx98-note@#dr62-unnamed {{unnamed type used in template argument was declared here}} + // cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}} int n1 = take(noNameForLinkagePtr); // cxx98-error@-1 {{template argument uses unnamed type}} - // cxx98-note@#dr62-unnamed {{unnamed type used in template argument was declared here}} + // cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}} X x4; @@ -1061,13 +1061,13 @@ namespace dr62 { // dr62: 2.9 } } -namespace dr63 { // dr63: yes +namespace cwg63 { // cwg63: yes template struct S { typename T::error e; }; extern S *p; void *q = p; } -namespace dr64 { // dr64: yes +namespace cwg64 { // cwg64: yes template void f(T); template void f(T*); template<> void f(int*); @@ -1075,11 +1075,11 @@ namespace dr64 { // dr64: yes template<> void f(int); } -// dr65: na +// cwg65: na -namespace dr66 { // dr66: no +namespace cwg66 { // cwg66: no namespace X { - int f(int n); // #dr66-f-first + int f(int n); // #cwg66-f-first } using X::f; namespace X { @@ -1089,36 +1089,36 @@ namespace dr66 { // dr66: no // FIXME: The first two calls here should be accepted. int a = f(); // expected-error@-1 {{no matching function for call to 'f'}} - // expected-note@#dr66-f-first {{candidate function not viable: requires single argument 'n', but no arguments were provided}} + // expected-note@#cwg66-f-first {{candidate function not viable: requires single argument 'n', but no arguments were provided}} int b = f(1); int c = f(1, 2); // expected-error@-1 {{no matching function for call to 'f'}} - // expected-note@#dr66-f-first {{candidate function not viable: requires single argument 'n', but 2 arguments were provided}} + // expected-note@#cwg66-f-first {{candidate function not viable: requires single argument 'n', but 2 arguments were provided}} } -// dr67: na +// cwg67: na -namespace dr68 { // dr68: 2.8 +namespace cwg68 { // cwg68: 2.8 template struct X {}; - struct ::dr68::X x1; - struct ::dr68::template X x2; + struct ::cwg68::X x1; + struct ::cwg68::template X x2; // cxx98-error@-1 {{'template' keyword outside of a template}} struct Y { friend struct X; - friend struct ::dr68::X; - friend struct ::dr68::template X; + friend struct ::cwg68::X; + friend struct ::cwg68::template X; // cxx98-error@-1 {{'template' keyword outside of a template}} }; template struct Z { - friend struct ::dr68::template X; - friend typename ::dr68::X; - // cxx98-error@-1 {{unelaborated friend declaration is a C++11 extension; specify 'struct' to befriend 'typename ::dr68::X'}} + friend struct ::cwg68::template X; + friend typename ::cwg68::X; + // cxx98-error@-1 {{unelaborated friend declaration is a C++11 extension; specify 'struct' to befriend 'typename ::cwg68::X'}} }; } -namespace dr69 { // dr69: 9 - template static void f() {} // #dr69-f +namespace cwg69 { // cwg69: 9 + template static void f() {} // #cwg69-f // FIXME: Should we warn here? inline void g() { f(); } extern template void f(); @@ -1127,21 +1127,21 @@ namespace dr69 { // dr69: 9 template struct Q {}; Q<&f > q; // cxx98-error@-1 {{non-type template argument referring to function 'f' with internal linkage is a C++11 extension}} - // cxx98-note@#dr69-f {{non-type template argument refers to function here}} + // cxx98-note@#cwg69-f {{non-type template argument refers to function here}} } -namespace dr70 { // dr70: yes +namespace cwg70 { // cwg70: yes template struct A {}; template int f(int (&)[I + J], A, A); int arr[7]; int k = f(arr, A<3>(), A<4>()); } -// dr71: na -// dr72: dup 69 +// cwg71: na +// cwg72: dup 69 #if __cplusplus >= 201103L -namespace dr73 { // dr73: sup 1652 +namespace cwg73 { // cwg73: sup 1652 int a, b; static_assert(&a + 1 != &b, ""); // expected-error@-1 {{static assertion expression is not an integral constant expression}} @@ -1149,43 +1149,43 @@ namespace dr73 { // dr73: sup 1652 } #endif -namespace dr74 { // dr74: yes +namespace cwg74 { // cwg74: yes enum E { k = 5 }; int (*p)[k] = new int[k][k]; } -namespace dr75 { // dr75: yes +namespace cwg75 { // cwg75: yes struct S { static int n = 0; // expected-error@-1 {{non-const static data member must be initialized out of line}} }; } -namespace dr76 { // dr76: yes +namespace cwg76 { // cwg76: yes const volatile int n = 1; - int arr[n]; // #dr76-vla - // expected-error@#dr76-vla {{variable length arrays in C++ are a Clang extension}} - // expected-note@#dr76-vla {{read of volatile-qualified type 'const volatile int' is not allowed in a constant expression}} - // expected-error@#dr76-vla {{variable length array declaration not allowed at file scope}} + int arr[n]; // #cwg76-vla + // expected-error@#cwg76-vla {{variable length arrays in C++ are a Clang extension}} + // expected-note@#cwg76-vla {{read of volatile-qualified type 'const volatile int' is not allowed in a constant expression}} + // expected-error@#cwg76-vla {{variable length array declaration not allowed at file scope}} } -namespace dr77 { // dr77: yes +namespace cwg77 { // cwg77: yes struct A { struct B {}; friend struct B; }; } -namespace dr78 { // dr78: sup ???? - // Under DR78, this is valid, because 'k' has static storage duration, so is +namespace cwg78 { // cwg78: sup ???? + // Under CWG78, this is valid, because 'k' has static storage duration, so is // zero-initialized. const int k; // expected-error@-1 {{default initialization of an object of const type 'const int'}} } -// dr79: na +// cwg79: na -namespace dr80 { // dr80: 2.9 +namespace cwg80 { // cwg80: 2.9 struct A { int A; }; @@ -1205,22 +1205,22 @@ namespace dr80 { // dr80: 2.9 }; } -// dr81: na -// dr82: dup 48 +// cwg81: na +// cwg82: dup 48 -namespace dr83 { // dr83: yes +namespace cwg83 { // cwg83: yes int &f(const char*); char &f(char *); int &k = f("foo"); } -namespace dr84 { // dr84: yes +namespace cwg84 { // cwg84: yes struct B; struct A { operator B() const; }; struct C {}; struct B { - B(B&); // #dr84-copy-ctor - B(C); // #dr84-ctor-from-C + B(B&); // #cwg84-copy-ctor + B(C); // #cwg84-ctor-from-C operator C() const; }; A a; @@ -1228,78 +1228,78 @@ namespace dr84 { // dr84: yes // here. In C++17, we initialize the B object directly using 'A::operator B()'. B b = a; // cxx98-14-error@-1 {{no viable constructor copying variable of type 'B'}} - // cxx98-14-note@#dr84-copy-ctor {{candidate constructor not viable: expects an lvalue for 1st argument}} - // cxx98-14-note@#dr84-ctor-from-C {{candidate constructor not viable: no known conversion from 'B' to 'C' for 1st argument}} + // cxx98-14-note@#cwg84-copy-ctor {{candidate constructor not viable: expects an lvalue for 1st argument}} + // cxx98-14-note@#cwg84-ctor-from-C {{candidate constructor not viable: no known conversion from 'B' to 'C' for 1st argument}} } -namespace dr85 { // dr85: 3.4 +namespace cwg85 { // cwg85: 3.4 struct A { struct B; - struct B {}; // #dr85-B-def + struct B {}; // #cwg85-B-def struct B; // expected-error@-1 {{class member cannot be redeclared}} - // expected-note@#dr85-B-def {{previous declaration is here}} + // expected-note@#cwg85-B-def {{previous declaration is here}} union U; - union U {}; // #dr85-U-def + union U {}; // #cwg85-U-def union U; // expected-error@-1 {{class member cannot be redeclared}} - // expected-note@#dr85-U-def {{previous declaration is here}} + // expected-note@#cwg85-U-def {{previous declaration is here}} #if __cplusplus >= 201103L enum E1 : int; - enum E1 : int { e1 }; // #dr85-E1-def + enum E1 : int { e1 }; // #cwg85-E1-def enum E1 : int; // expected-error@-1 {{class member cannot be redeclared}} - // expected-note@#dr85-E1-def {{previous declaration is here}} + // expected-note@#cwg85-E1-def {{previous declaration is here}} enum class E2; - enum class E2 { e2 }; // #dr85-E2-def + enum class E2 { e2 }; // #cwg85-E2-def enum class E2; // expected-error@-1 {{class member cannot be redeclared}} - // expected-note@#dr85-E2-def {{previous declaration is here}} + // expected-note@#cwg85-E2-def {{previous declaration is here}} #endif }; template struct C { - struct B {}; // #dr85-C-B-def + struct B {}; // #cwg85-C-B-def struct B; // expected-error@-1 {{class member cannot be redeclared}} - // expected-note@#dr85-C-B-def {{previous declaration is here}} + // expected-note@#cwg85-C-B-def {{previous declaration is here}} }; } -// dr86: dup 446 +// cwg86: dup 446 -namespace dr87 { // dr87: no - // FIXME: Superseded by dr1975 +namespace cwg87 { // cwg87: no + // FIXME: Superseded by cwg1975 template struct X {}; // FIXME: This is invalid. X x; - // This is valid under dr87 but not under dr1975. + // This is valid under cwg87 but not under cwg1975. X y; } -namespace dr88 { // dr88: 2.8 +namespace cwg88 { // cwg88: 2.8 template struct S { - static const int a = 1; // #dr88-a + static const int a = 1; // #cwg88-a static const int b; }; template<> const int S::a = 4; // expected-error@-1 {{static data member 'a' already has an initializer}} - // expected-note@#dr88-a {{previous initialization is here}} + // expected-note@#cwg88-a {{previous initialization is here}} template<> const int S::b = 4; } -// dr89: na +// cwg89: na -namespace dr90 { // dr90: yes +namespace cwg90 { // cwg90: yes struct A { - template friend void dr90_f(T); + template friend void cwg90_f(T); }; struct B : A { - template friend void dr90_g(T); + template friend void cwg90_g(T); struct C {}; union D {}; }; @@ -1307,41 +1307,41 @@ namespace dr90 { // dr90: yes struct F : B::C {}; void test() { - dr90_f(A()); - dr90_f(B()); - dr90_f(B::C()); - // expected-error@-1 {{use of undeclared identifier 'dr90_f'}} - dr90_f(B::D()); - // expected-error@-1 {{use of undeclared identifier 'dr90_f'}} - dr90_f(E()); - dr90_f(F()); - // expected-error@-1 {{use of undeclared identifier 'dr90_f'}} - - dr90_g(A()); - // expected-error@-1 {{use of undeclared identifier 'dr90_g'}} - dr90_g(B()); - dr90_g(B::C()); - dr90_g(B::D()); - dr90_g(E()); - dr90_g(F()); - // expected-error@-1 {{use of undeclared identifier 'dr90_g'}} + cwg90_f(A()); + cwg90_f(B()); + cwg90_f(B::C()); + // expected-error@-1 {{use of undeclared identifier 'cwg90_f'}} + cwg90_f(B::D()); + // expected-error@-1 {{use of undeclared identifier 'cwg90_f'}} + cwg90_f(E()); + cwg90_f(F()); + // expected-error@-1 {{use of undeclared identifier 'cwg90_f'}} + + cwg90_g(A()); + // expected-error@-1 {{use of undeclared identifier 'cwg90_g'}} + cwg90_g(B()); + cwg90_g(B::C()); + cwg90_g(B::D()); + cwg90_g(E()); + cwg90_g(F()); + // expected-error@-1 {{use of undeclared identifier 'cwg90_g'}} } } -namespace dr91 { // dr91: yes +namespace cwg91 { // cwg91: yes union U { friend int f(U); }; int k = f(U()); } -namespace dr92 { // dr92: 4 c++17 +namespace cwg92 { // cwg92: 4 c++17 void f() throw(int, float); // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} - void (*p)() throw(int) = &f; // #dr92-p - // since-cxx17-error@#dr92-p {{ISO C++17 does not allow dynamic exception specifications}} - // since-cxx17-note@#dr92-p {{use 'noexcept(false)' instead}} - // cxx98-14-error@#dr92-p {{target exception specification is not superset of source}} - // since-cxx17-warning@#dr92-p {{target exception specification is not superset of source}} + void (*p)() throw(int) = &f; // #cwg92-p + // since-cxx17-error@#cwg92-p {{ISO C++17 does not allow dynamic exception specifications}} + // since-cxx17-note@#cwg92-p {{use 'noexcept(false)' instead}} + // cxx98-14-error@#cwg92-p {{target exception specification is not superset of source}} + // since-cxx17-warning@#cwg92-p {{target exception specification is not superset of source}} void (*q)() throw(int); // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} @@ -1349,17 +1349,17 @@ namespace dr92 { // dr92: 4 c++17 // cxx98-14-error@-1 {{exception specifications are not allowed beyond a single level of indirection}} // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (**)() throw()' with an rvalue of type 'void (**)() throw(int)'}} - void g(void() throw()); // #dr92-g + void g(void() throw()); // #cwg92-g // cxx98-14-warning@-1 {{mangled name of 'g' will change in C++17 due to non-throwing exception specification in function signature}} void h() throw() { g(f); // cxx98-14-error@-1 {{target exception specification is not superset of source}} // since-cxx17-error@-2 {{no matching function for call to 'g'}} - // since-cxx17-note@#dr92-g {{candidate function not viable: no known conversion from 'void () throw(int, float)' to 'void (*)() throw()' for 1st argument}} + // since-cxx17-note@#cwg92-g {{candidate function not viable: no known conversion from 'void () throw(int, float)' to 'void (*)() throw()' for 1st argument}} g(q); // cxx98-14-error@-1 {{target exception specification is not superset of source}} // since-cxx17-error@-2 {{no matching function for call to 'g'}} - // since-cxx17-note@#dr92-g {{candidate function not viable: no known conversion from 'void (*)() throw(int)' to 'void (*)() throw()' for 1st argument}} + // since-cxx17-note@#cwg92-g {{candidate function not viable: no known conversion from 'void (*)() throw(int)' to 'void (*)() throw()' for 1st argument}} } // Prior to C++17, this is OK because the exception specification is not @@ -1376,31 +1376,31 @@ namespace dr92 { // dr92: 4 c++17 Y<&h> yp; // ok } -// dr93: na +// cwg93: na -namespace dr94 { // dr94: yes +namespace cwg94 { // cwg94: yes struct A { static const int n = 5; }; int arr[A::n]; } -namespace dr95 { // dr95: 3.3 +namespace cwg95 { // cwg95: 3.3 struct A; struct B; namespace N { class C { friend struct A; friend struct B; - static void f(); // #dr95-C-f + static void f(); // #cwg95-C-f }; - struct A *p; // dr95::A, not dr95::N::A. + struct A *p; // cwg95::A, not cwg95::N::A. } A *q = N::p; // ok, same type struct B { void f() { N::C::f(); } }; - // expected-error@-1 {{'f' is a private member of 'dr95::N::C'}} - // expected-note@#dr95-C-f {{implicitly declared private here}} + // expected-error@-1 {{'f' is a private member of 'cwg95::N::C'}} + // expected-note@#cwg95-C-f {{implicitly declared private here}} } -namespace dr96 { // dr96: no +namespace cwg96 { // cwg96: no struct A { void f(int); template int f(T); @@ -1420,42 +1420,42 @@ namespace dr96 { // dr96: no } } -namespace dr97 { // dr97: yes +namespace cwg97 { // cwg97: yes struct A { static const int a = false; static const int b = !a; }; } -namespace dr98 { // dr98: yes +namespace cwg98 { // cwg98: yes void test(int n) { switch (n) { - try { // #dr98-try + try { // #cwg98-try case 0: // expected-error@-1 {{cannot jump from switch statement to this case label}} - // expected-note@#dr98-try {{jump bypasses initialization of try block}} + // expected-note@#cwg98-try {{jump bypasses initialization of try block}} x: throw n; - } catch (...) { // #dr98-catch + } catch (...) { // #cwg98-catch case 1: // expected-error@-1 {{cannot jump from switch statement to this case label}} - // expected-note@#dr98-catch {{jump bypasses initialization of catch block}} + // expected-note@#cwg98-catch {{jump bypasses initialization of catch block}} y: throw n; } case 2: goto x; // expected-error@-1 {{cannot jump from this goto statement to its label}} - // expected-note@#dr98-try {{jump bypasses initialization of try block}} + // expected-note@#cwg98-try {{jump bypasses initialization of try block}} case 3: goto y; // expected-error@-1 {{cannot jump from this goto statement to its label}} - // expected-note@#dr98-catch {{jump bypasses initialization of catch block}} + // expected-note@#cwg98-catch {{jump bypasses initialization of catch block}} } } } -namespace dr99 { // dr99: sup 214 +namespace cwg99 { // cwg99: sup 214 template void f(T&); template int &f(const T&); const int n = 0; diff --git a/clang/test/CXX/drs/dr10xx.cpp b/clang/test/CXX/drs/dr10xx.cpp index 77c59078414c69bdb012207d68ba774cf41f64e2..58d552942c77cca22d8180222a962a020d105d76 100644 --- a/clang/test/CXX/drs/dr10xx.cpp +++ b/clang/test/CXX/drs/dr10xx.cpp @@ -14,26 +14,26 @@ namespace std { }; } -namespace dr1004 { // dr1004: 5 +namespace cwg1004 { // cwg1004: 5 template struct A {}; template struct B1 {}; template class> struct B2 {}; - template void f(); // #dr1004-f-1 - template class X> void f(); // #dr1004-f-2 - template class X> void g(); // #dr1004-g-1 - template void g(); // #dr1004-g-2 + template void f(); // #cwg1004-f-1 + template class X> void f(); // #cwg1004-f-2 + template class X> void g(); // #cwg1004-g-1 + template void g(); // #cwg1004-g-2 struct C : A { B1 b1a; B2 b2a; void h() { f(); // expected-error@-1 {{call to 'f' is ambiguous}} - // expected-note@#dr1004-f-1 {{candidate function [with X = dr1004::A]}} - // expected-note@#dr1004-f-2 {{candidate function [with X = dr1004::A]}} + // expected-note@#cwg1004-f-1 {{candidate function [with X = cwg1004::A]}} + // expected-note@#cwg1004-f-2 {{candidate function [with X = cwg1004::A]}} g(); // expected-error@-1 {{call to 'g' is ambiguous}} - // expected-note@#dr1004-g-1 {{candidate function [with X = dr1004::A]}} - // expected-note@#dr1004-g-2 {{candidate function [with X = dr1004::A]}} + // expected-note@#cwg1004-g-1 {{candidate function [with X = cwg1004::A]}} + // expected-note@#cwg1004-g-2 {{candidate function [with X = cwg1004::A]}} } }; @@ -41,17 +41,17 @@ namespace dr1004 { // dr1004: 5 // name lookup of "T::template A" names the constructor. template class U = T::template A> struct Third { }; // expected-error@-1 {{is a constructor name}} - // expected-note@#dr1004-t {{in instantiation of default argument}} - Third > t; // #dr1004-t + // expected-note@#cwg1004-t {{in instantiation of default argument}} + Third > t; // #cwg1004-t } -namespace dr1042 { // dr1042: 3.5 +namespace cwg1042 { // cwg1042: 3.5 #if __cplusplus >= 201402L // C++14 added an attribute that we can test the semantics of. - using foo [[deprecated]] = int; // #dr1042-using + using foo [[deprecated]] = int; // #cwg1042-using foo f = 12; // since-cxx14-warning@-1 {{'foo' is deprecated}} - // since-cxx14-note@#dr1042-using {{'foo' has been explicitly marked deprecated here}} + // since-cxx14-note@#cwg1042-using {{'foo' has been explicitly marked deprecated here}} #elif __cplusplus >= 201103L // C++11 did not have any attributes that could be applied to an alias // declaration, so the best we can test is that we accept an empty attribute @@ -60,7 +60,7 @@ namespace dr1042 { // dr1042: 3.5 #endif } -namespace dr1048 { // dr1048: 3.6 +namespace cwg1048 { // cwg1048: 3.6 struct A {}; const A f(); A g(); @@ -78,20 +78,20 @@ namespace dr1048 { // dr1048: 3.6 #endif } -namespace dr1054 { // dr1054: no +namespace cwg1054 { // cwg1054: no // FIXME: Test is incomplete. struct A {} volatile a; void f() { // FIXME: This is wrong: an lvalue-to-rvalue conversion is applied here, // which copy-initializes a temporary from 'a'. Therefore this is // ill-formed because A does not have a volatile copy constructor. - // (We might want to track this aspect under dr1383 instead?) + // (We might want to track this aspect under cwg1383 instead?) a; // expected-warning@-1 {{expression result unused; assign into a variable to force a volatile load}} } } -namespace dr1070 { // dr1070: 3.5 +namespace cwg1070 { // cwg1070: 3.5 #if __cplusplus >= 201103L struct A { A(std::initializer_list); diff --git a/clang/test/CXX/drs/dr11xx.cpp b/clang/test/CXX/drs/dr11xx.cpp index a71a105c7eb20470200b92b17f685a37b1582bb2..46a0e526be390c5ab6e3df3947eb85897eb3feff 100644 --- a/clang/test/CXX/drs/dr11xx.cpp +++ b/clang/test/CXX/drs/dr11xx.cpp @@ -4,27 +4,27 @@ // RUN: %clang_cc1 -std=c++17 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2a %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors -namespace dr1111 { // dr1111: 3.2 +namespace cwg1111 { // cwg1111: 3.2 namespace example1 { -template struct set; // #dr1111-struct-set +template struct set; // #cwg1111-struct-set struct X { - template void set(const T &value); // #dr1111-func-set + template void set(const T &value); // #cwg1111-func-set }; void foo() { X x; // FIXME: should we backport C++11 behavior? x.set(3.2); // cxx98-error@-1 {{lookup of 'set' in member access expression is ambiguous; using member of 'X'}} - // cxx98-note@#dr1111-func-set {{lookup in the object type 'X' refers here}} - // cxx98-note@#dr1111-struct-set {{lookup from the current scope refers here}} + // cxx98-note@#cwg1111-func-set {{lookup in the object type 'X' refers here}} + // cxx98-note@#cwg1111-struct-set {{lookup from the current scope refers here}} } struct Y {}; void bar() { Y y; y.set(3.2); - // expected-error@-1 {{no member named 'set' in 'dr1111::example1::Y'}} + // expected-error@-1 {{no member named 'set' in 'cwg1111::example1::Y'}} } } // namespace example1 @@ -42,14 +42,14 @@ void baz() { a.operator A(); } } // namespace example2 -} // namespace dr1111 +} // namespace cwg1111 -namespace dr1113 { // dr1113: partial +namespace cwg1113 { // cwg1113: partial namespace named { - extern int a; // #dr1113-a + extern int a; // #cwg1113-a static int a; // expected-error@-1 {{static declaration of 'a' follows non-static}} - // expected-note@#dr1113-a {{previous declaration is here}} + // expected-note@#cwg1113-a {{previous declaration is here}} } namespace { extern int a; @@ -57,7 +57,7 @@ namespace dr1113 { // dr1113: partial int b = a; } - // FIXME: Per DR1113 and DR4, this is ill-formed due to ambiguity: the second + // FIXME: Per CWG1113 and CWG4, this is ill-formed due to ambiguity: the second // 'f' has internal linkage, and so does not have C language linkage, so is // not a redeclaration of the first 'f'. // @@ -71,4 +71,4 @@ namespace dr1113 { // dr1113: partial void g() { f(); } } -// dr1150: na +// cwg1150: na diff --git a/clang/test/CXX/drs/dr12xx.cpp b/clang/test/CXX/drs/dr12xx.cpp index da5dd02a00677c6a966558435770a3cde01788e2..cdfbc6d6726581e467ae67205321def722dd7f58 100644 --- a/clang/test/CXX/drs/dr12xx.cpp +++ b/clang/test/CXX/drs/dr12xx.cpp @@ -5,9 +5,9 @@ // RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx17,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx17,since-cxx14,since-cxx11,since-cxx23 -fexceptions -fcxx-exceptions -pedantic-errors -// dr1200: na +// cwg1200: na -namespace dr1213 { // dr1213: 7 +namespace cwg1213 { // cwg1213: 7 #if __cplusplus >= 201103L using T = int[3]; int &&r = T{}[1]; @@ -32,7 +32,7 @@ namespace dr1213 { // dr1213: 7 } #if __cplusplus >= 201103L -namespace dr1223 { // dr1223: 17 drafting 2023-05-12 +namespace cwg1223 { // cwg1223: 17 drafting 2023-05-12 struct M; template struct V; @@ -80,31 +80,31 @@ void g() { A b(auto ()->C); static_assert(sizeof(B ()->C[1] == sizeof(int)), ""); sizeof(auto () -> C[1]); - // since-cxx11-error@-1 {{function cannot return array type 'C[1]' (aka 'dr1223::BB[1]')}} + // since-cxx11-error@-1 {{function cannot return array type 'C[1]' (aka 'cwg1223::BB[1]')}} } } #endif #if __cplusplus >= 201103L -namespace dr1227 { // dr1227: 3.0 +namespace cwg1227 { // cwg1227: 3.0 template struct A { using X = typename T::X; }; // since-cxx11-error@-1 {{type 'int' cannot be used prior to '::' because it has no members}} -// since-cxx11-note@#dr1227-g {{in instantiation of template class 'dr1227::A' requested here}} -// since-cxx11-note@#dr1227-g-int {{while substituting explicitly-specified template arguments into function template 'g'}} +// since-cxx11-note@#cwg1227-g {{in instantiation of template class 'cwg1227::A' requested here}} +// since-cxx11-note@#cwg1227-g-int {{while substituting explicitly-specified template arguments into function template 'g'}} template typename T::X f(typename A::X); template void f(...) { } -template auto g(typename A::X) -> typename T::X; // #dr1227-g +template auto g(typename A::X) -> typename T::X; // #cwg1227-g template void g(...) { } void h() { f(0); // OK, substituting return type causes deduction to fail - g(0); // #dr1227-g-int + g(0); // #cwg1227-g-int } } #endif -namespace dr1250 { // dr1250: 3.9 +namespace cwg1250 { // cwg1250: 3.9 struct Incomplete; struct Base { @@ -116,7 +116,7 @@ struct Derived : Base { }; } -namespace dr1265 { // dr1265: 5 +namespace cwg1265 { // cwg1265: 5 #if __cplusplus >= 201103L auto a = 0, b() -> int; // since-cxx11-error@-1 {{declaration with trailing return type must be the only declaration in its group}} @@ -136,9 +136,9 @@ namespace dr1265 { // dr1265: 5 #endif } -// dr1291: na +// cwg1291: na -namespace dr1295 { // dr1295: 4 +namespace cwg1295 { // cwg1295: 4 struct X { unsigned bitfield : 4; }; @@ -150,11 +150,11 @@ namespace dr1295 { // dr1295: 4 unsigned const &r2 = static_cast(x.bitfield); // cxx98-error@-1 {{rvalue references are a C++11 extension}} - template struct Y {}; // #dr1295-Y - Y y; // #dr1295-y + template struct Y {}; // #cwg1295-Y + Y y; // #cwg1295-y // cxx98-14-error@-1 {{non-type template argument does not refer to any declaration}} - // cxx98-14-note@#dr1295-Y {{template parameter is declared here}} - // since-cxx17-error@#dr1295-y {{reference cannot bind to bit-field in converted constant expression}} + // cxx98-14-note@#cwg1295-Y {{template parameter is declared here}} + // since-cxx17-error@#cwg1295-y {{reference cannot bind to bit-field in converted constant expression}} #if __cplusplus >= 201103L const unsigned other = 0; diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp index d8e3b5d87bd149043e2b00062760ad7607018c5d..dad82c4e2829f013507e1b04dc2ac3062c866a2a 100644 --- a/clang/test/CXX/drs/dr13xx.cpp +++ b/clang/test/CXX/drs/dr13xx.cpp @@ -17,18 +17,18 @@ namespace std { } #if __cplusplus >= 201103L -namespace dr1305 { // dr1305: 3.0 -struct Incomplete; // #dr1305-Incomplete +namespace cwg1305 { // cwg1305: 3.0 +struct Incomplete; // #cwg1305-Incomplete struct Complete {}; int incomplete = alignof(Incomplete(&)[]); // since-cxx11-error@-1 {{invalid application of 'alignof' to an incomplete type 'Incomplete'}} -// since-cxx11-note@#dr1305-Incomplete {{forward declaration of 'dr1305::Incomplete'}} +// since-cxx11-note@#cwg1305-Incomplete {{forward declaration of 'cwg1305::Incomplete'}} int complete = alignof(Complete(&)[]); } #endif -namespace dr1307 { // dr1307: 14 +namespace cwg1307 { // cwg1307: 14 #if __cplusplus >= 201103L void f(int const (&)[2]); void f(int const (&)[3]); @@ -38,11 +38,11 @@ void caller() { f({1, 2, 3}); } #endif // __cplusplus >= 201103L -} // namespace dr1307 +} // namespace cwg1307 -// dr1308: sup 1330 +// cwg1308: sup 1330 -namespace dr1310 { // dr1310: 5 +namespace cwg1310 { // cwg1310: 5 struct S {} * sp = new S::S; // expected-error@-1 {{qualified reference to 'S' is a constructor name rather than a type in this context}} void f() { @@ -126,8 +126,8 @@ namespace dr1310 { // dr1310: 5 void wt_test() { typename W::W w2a; // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' is a constructor name rather than a type in this context, despite preceding 'typename' keyword}} - // cxx98-note@#dr1310-W-int {{in instantiation of function template specialization 'dr1310::wt_test >' requested here}} - // since-cxx11-note@#dr1310-W-int {{in instantiation of function template specialization 'dr1310::wt_test>' requested here}} + // cxx98-note@#cwg1310-W-int {{in instantiation of function template specialization 'cwg1310::wt_test >' requested here}} + // since-cxx11-note@#cwg1310-W-int {{in instantiation of function template specialization 'cwg1310::wt_test>' requested here}} typename W::template W w4; // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' is a constructor name rather than a template name in this context, despite preceding 'template' keyword}} TTy tt2; @@ -148,11 +148,11 @@ namespace dr1310 { // dr1310: 5 (void)w.template W::W::n; (void)w.template W::template W::n; } - template void wt_test >(); // #dr1310-W-int + template void wt_test >(); // #cwg1310-W-int template void wt_test_good >(); } -namespace dr1315 { // dr1315: partial +namespace cwg1315 { // cwg1315: partial template struct A {}; template struct A {}; // expected-error@-1 {{class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used}} @@ -160,7 +160,7 @@ namespace dr1315 { // dr1315: partial template struct A {}; template struct B; - template struct B {}; // #dr1315-B-1 + template struct B {}; // #cwg1315-B-1 B<1, 2, 3> b1; // Multiple declarations with the same dependent expression are equivalent @@ -169,13 +169,13 @@ namespace dr1315 { // dr1315: partial B<1, 2, 2>::type b2; // Multiple declarations with differing dependent expressions are unordered. - template struct B {}; // #dr1315-B-2 + template struct B {}; // #cwg1315-B-2 B<1, 2, 4> b3; // expected-error@-1 {{ambiguous partial specializations of 'B<1, 2, 4>'}} - // expected-note@#dr1315-B-1 {{partial specialization matches [with I = 1, K = 4]}} - // expected-note@#dr1315-B-2 {{partial specialization matches [with I = 1, K = 4]}} + // expected-note@#cwg1315-B-1 {{partial specialization matches [with I = 1, K = 4]}} + // expected-note@#cwg1315-B-2 {{partial specialization matches [with I = 1, K = 4]}} - // FIXME: Under dr1315, this is perhaps valid, but that is not clear: this + // FIXME: Under cwg1315, this is perhaps valid, but that is not clear: this // fails the "more specialized than the primary template" test because the // dependent type of T::value is not the same as 'int'. // A core issue will be opened to decide what is supposed to happen here. @@ -184,7 +184,7 @@ namespace dr1315 { // dr1315: partial // expected-error@-1 {{type of specialized non-type template argument depends on a template parameter of the partial specialization}} } -namespace dr1330 { // dr1330: 4 c++11 +namespace cwg1330 { // cwg1330: 4 c++11 // exception-specifications are parsed in a context where the class is complete. struct A { void f() throw(T) {} @@ -204,7 +204,7 @@ namespace dr1330 { // dr1330: 4 c++11 // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} void (A::*af2)() throw() = &A::f; // cxx98-14-error@-1 {{target exception specification is not superset of source}} - // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (dr1330::A::*)() throw()' with an rvalue of type 'void (dr1330::A::*)() throw(T)': different exception specifications}} + // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (cwg1330::A::*)() throw()' with an rvalue of type 'void (cwg1330::A::*)() throw(T)': different exception specifications}} #if __cplusplus >= 201103L static_assert(noexcept(A().g()), ""); @@ -252,7 +252,7 @@ namespace dr1330 { // dr1330: 4 c++11 void (B

::*bpf3)() = &B

::f; void (B

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

::f; // cxx98-14-error@-1 {{target exception specification is not superset of source}} - // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (B

::*)() throw()' with an rvalue of type 'void (dr1330::B::*)() throw(T, typename P::type)': different exception specifications}} + // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (B

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

().g()), ""); @@ -260,73 +260,73 @@ namespace dr1330 { // dr1330: 4 c++11 static_assert(!noexcept(B().g()), ""); #endif - template int f() throw(typename T::error) { return 0; } // #dr1330-f - // expected-error@#dr1330-f {{type 'int' cannot be used prior to '::' because it has no members}} - // cxx98-note@#dr1330-f-int {{in instantiation of function template specialization 'dr1330::f' requested here}} - // since-cxx11-note@#dr1330-f-int {{in instantiation of exception specification for 'f' requested here}} - // cxx98-14-error@#dr1330-f {{type 'short' cannot be used prior to '::' because it has no members}} - // cxx98-14-note@#dr1330-f-short {{in instantiation of function template specialization 'dr1330::f' requested here}} - // cxx11-14-note@#dr1330-f {{in instantiation of exception specification for 'f' requested here}} - // since-cxx11-error@#dr1330-f {{type 'char' cannot be used prior to '::' because it has no members}} - // since-cxx11-note@#dr1330-f-char {{in instantiation of exception specification for 'f' requested here}} - // since-cxx11-error@#dr1330-f {{type 'float' cannot be used prior to '::' because it has no members}} - // since-cxx11-note@#dr1330-f-float {{in instantiation of exception specification for 'f' requested here}} - // since-cxx17-error@#dr1330-f {{ISO C++17 does not allow dynamic exception specifications}} - // since-cxx17-note@#dr1330-f {{use 'noexcept(false)' instead}} + template int f() throw(typename T::error) { return 0; } // #cwg1330-f + // expected-error@#cwg1330-f {{type 'int' cannot be used prior to '::' because it has no members}} + // cxx98-note@#cwg1330-f-int {{in instantiation of function template specialization 'cwg1330::f' requested here}} + // since-cxx11-note@#cwg1330-f-int {{in instantiation of exception specification for 'f' requested here}} + // cxx98-14-error@#cwg1330-f {{type 'short' cannot be used prior to '::' because it has no members}} + // cxx98-14-note@#cwg1330-f-short {{in instantiation of function template specialization 'cwg1330::f' requested here}} + // cxx11-14-note@#cwg1330-f {{in instantiation of exception specification for 'f' requested here}} + // since-cxx11-error@#cwg1330-f {{type 'char' cannot be used prior to '::' because it has no members}} + // since-cxx11-note@#cwg1330-f-char {{in instantiation of exception specification for 'f' requested here}} + // since-cxx11-error@#cwg1330-f {{type 'float' cannot be used prior to '::' because it has no members}} + // since-cxx11-note@#cwg1330-f-float {{in instantiation of exception specification for 'f' requested here}} + // since-cxx17-error@#cwg1330-f {{ISO C++17 does not allow dynamic exception specifications}} + // since-cxx17-note@#cwg1330-f {{use 'noexcept(false)' instead}} // An exception-specification is needed even if the function is only used in // an unevaluated operand. - int f1 = sizeof(f()); // #dr1330-f-int + int f1 = sizeof(f()); // #cwg1330-f-int #if __cplusplus >= 201103L - decltype(f()) f2; // #dr1330-f-char - bool f3 = noexcept(f()); /// #dr1330-f-float + decltype(f()) f2; // #cwg1330-f-char + bool f3 = noexcept(f()); /// #cwg1330-f-float #endif // In C++17 onwards, substituting explicit template arguments into the // function type substitutes into the exception specification (because it's // part of the type). In earlier languages, we don't notice there's a problem // until we've already started to instantiate. - template int f(); // #dr1330-f-short + template int f(); // #cwg1330-f-short // since-cxx17-error@-1 {{explicit instantiation of 'f' does not refer to a function template, variable template, member function, member class, or static data member}} - // since-cxx17-note@#dr1330-f {{candidate template ignored: substitution failure [with T = short]: type 'short' cannot be used prior to '::' because it has no members}} + // since-cxx17-note@#cwg1330-f {{candidate template ignored: substitution failure [with T = short]: type 'short' cannot be used prior to '::' because it has no members}} template struct C { - C() throw(typename T::type); // #dr1330-C + C() throw(typename T::type); // #cwg1330-C // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} - // cxx98-error@#dr1330-C {{type 'void' cannot be used prior to '::' because it has no members}} - // cxx98-note@#dr1330-C-void {{in instantiation of template class 'dr1330::C' requested here}} - // expected-error@#dr1330-C {{type 'int' cannot be used prior to '::' because it has no members}} - // cxx98-note@#dr1330-C-int {{in instantiation of template class 'dr1330::C' requested here}} - // since-cxx11-note@#dr1330-C-int {{in instantiation of exception specification for 'C' requested here}} - // since-cxx11-note@#dr1330-e {{in evaluation of exception specification for 'dr1330::E::E' needed here}} + // cxx98-error@#cwg1330-C {{type 'void' cannot be used prior to '::' because it has no members}} + // cxx98-note@#cwg1330-C-void {{in instantiation of template class 'cwg1330::C' requested here}} + // expected-error@#cwg1330-C {{type 'int' cannot be used prior to '::' because it has no members}} + // cxx98-note@#cwg1330-C-int {{in instantiation of template class 'cwg1330::C' requested here}} + // since-cxx11-note@#cwg1330-C-int {{in instantiation of exception specification for 'C' requested here}} + // since-cxx11-note@#cwg1330-e {{in evaluation of exception specification for 'cwg1330::E::E' needed here}} }; - struct D : C {}; // #dr1330-C-void + struct D : C {}; // #cwg1330-C-void void f(D &d) { d = d; } // ok - struct E : C {}; // #dr1330-C-int - E e; // #dr1330-e + struct E : C {}; // #cwg1330-C-int + E e; // #cwg1330-e } -// dr1334: sup 1719 +// cwg1334: sup 1719 -namespace dr1341 { // dr1341: sup P0683R1 +namespace cwg1341 { // cwg1341: sup P0683R1 #if __cplusplus >= 202002L int a; -const int b = 0; // #dr1341-b +const int b = 0; // #cwg1341-b struct S { int x1 : 8 = 42; int x2 : 8 { 42 }; int y1 : true ? 8 : a = 42; int y2 : true ? 8 : b = 42; // since-cxx20-error@-1 {{cannot assign to variable 'b' with const-qualified type 'const int'}} - // since-cxx20-note@#dr1341-b {{variable 'b' declared const here}} + // since-cxx20-note@#cwg1341-b {{variable 'b' declared const here}} int y3 : (true ? 8 : b) = 42; int z : 1 || new int { 0 }; }; #endif } -namespace dr1346 { // dr1346: 3.5 +namespace cwg1346 { // cwg1346: 3.5 auto a(1); // cxx98-error@-1 {{'auto' type specifier is a C++11 extension}} auto b(1, 2); @@ -345,9 +345,9 @@ namespace dr1346 { // dr1346: 3.5 auto x(ts...); // cxx98-error@-1 {{'auto' type specifier is a C++11 extension}} // expected-error@-2 {{initializer for variable 'x' with type 'auto' is empty}} - // expected-note@#dr1346-f {{in instantiation of function template specialization 'dr1346::f<>' requested here}} + // expected-note@#cwg1346-f {{in instantiation of function template specialization 'cwg1346::f<>' requested here}} } - template void f(); // #dr1346-f + template void f(); // #cwg1346-f #if __cplusplus >= 201103L void init_capture() { @@ -369,7 +369,7 @@ namespace dr1346 { // dr1346: 3.5 #endif } -namespace dr1347 { // dr1347: 3.1 +namespace cwg1347 { // cwg1347: 3.1 auto x = 5, *y = &x; // cxx98-error@-1 {{'auto' type specifier is a C++11 extension}} auto z = y, *q = y; @@ -383,7 +383,7 @@ namespace dr1347 { // dr1347: 3.1 #endif } -namespace dr1350 { // dr1350: 3.5 +namespace cwg1350 { // cwg1350: 3.5 #if __cplusplus >= 201103L struct NoexceptCtor { NoexceptCtor(int) noexcept {} @@ -452,12 +452,12 @@ struct D4 : NoexceptCtor, ThrowingDefaultArgTemplate { static_assert(!__is_nothrow_constructible(D4, int), ""); #endif -} // namespace dr1350 +} // namespace cwg1350 -namespace dr1358 { // dr1358: 3.1 +namespace cwg1358 { // cwg1358: 3.1 #if __cplusplus >= 201103L struct Lit { constexpr operator int() const { return 0; } }; - struct NonLit { NonLit(); operator int(); }; // #dr1358-NonLit + struct NonLit { NonLit(); operator int(); }; // #cwg1358-NonLit struct NonConstexprConv { constexpr operator int() const; }; struct Virt { virtual int f(int) const; }; @@ -486,83 +486,83 @@ namespace dr1358 { // dr1358: 3.1 int member; constexpr B(NonLit u) : member(u) {} // cxx11-20-error@-1 {{constexpr constructor's 1st parameter type 'NonLit' is not a literal type}} - // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + // cxx11-20-note@#cwg1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} constexpr NonLit f(NonLit u) const { return NonLit(); } // cxx11-20-error@-1 {{constexpr function's return type 'NonLit' is not a literal type}} - // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + // cxx11-20-note@#cwg1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} }; #endif } -namespace dr1359 { // dr1359: 3.5 +namespace cwg1359 { // cwg1359: 3.5 #if __cplusplus >= 201103L union A { constexpr A() = default; }; - union B { constexpr B() = default; int a; }; // #dr1359-B + union B { constexpr B() = default; int a; }; // #cwg1359-B // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr before C++23}} - union C { constexpr C() = default; int a, b; }; // #dr1359-C + union C { constexpr C() = default; int a, b; }; // #cwg1359-C // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} struct X { constexpr X() = default; union {}; }; // since-cxx11-error@-1 {{declaration does not declare anything}} - struct Y { constexpr Y() = default; union { int a; }; }; // #dr1359-Y + struct Y { constexpr Y() = default; union { int a; }; }; // #cwg1359-Y // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} constexpr A a = A(); constexpr B b = B(); // cxx11-17-error@-1 {{no matching constructor for initialization of 'B'}} - // cxx11-17-note@#dr1359-B {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} - // cxx11-17-note@#dr1359-B {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#cwg1359-B {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#cwg1359-B {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} constexpr C c = C(); // cxx11-17-error@-1 {{no matching constructor for initialization of 'C'}} - // cxx11-17-note@#dr1359-C {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} - // cxx11-17-note@#dr1359-C {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#cwg1359-C {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#cwg1359-C {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} constexpr X x = X(); constexpr Y y = Y(); // cxx11-17-error@-1 {{no matching constructor for initialization of 'Y'}} - // cxx11-17-note@#dr1359-Y {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} - // cxx11-17-note@#dr1359-Y {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#cwg1359-Y {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#cwg1359-Y {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} #endif } -namespace dr1388 { // dr1388: 4 - template void f(T..., A); // #dr1388-f +namespace cwg1388 { // cwg1388: 4 + template void f(T..., A); // #cwg1388-f // cxx98-error@-1 {{variadic templates are a C++11 extension}} - template void g(T..., int); // #dr1388-g + template void g(T..., int); // #cwg1388-g // cxx98-error@-1 {{variadic templates are a C++11 extension}} - template void h(T..., A); // #dr1388-h + template void h(T..., A); // #cwg1388-h // cxx98-error@-1 {{variadic templates are a C++11 extension}} void test_f() { f(0); // ok, trailing parameter pack deduced to empty f(0, 0); // expected-error@-1 {{no matching function for call to 'f'}} - // expected-note@#dr1388-f {{candidate function [with A = int, T = <>] not viable: requires 1 argument, but 2 were provided}} + // expected-note@#cwg1388-f {{candidate function [with A = int, T = <>] not viable: requires 1 argument, but 2 were provided}} f(0); f(0, 0); // expected-error@-1 {{no matching function for call to 'f'}} - // expected-note@#dr1388-f {{candidate function [with A = int, T = <>] not viable: requires 1 argument, but 2 were provided}} + // expected-note@#cwg1388-f {{candidate function [with A = int, T = <>] not viable: requires 1 argument, but 2 were provided}} f(0, 0); f(0, 0); // expected-error@-1 {{no matching function for call to 'f'}} - // expected-note@#dr1388-f {{candidate function [with A = int, T = ] not viable: requires 3 arguments, but 2 were provided}} + // expected-note@#cwg1388-f {{candidate function [with A = int, T = ] not viable: requires 3 arguments, but 2 were provided}} g(0); g(0, 0); // expected-error@-1 {{no matching function for call to 'g'}} - // expected-note@#dr1388-g {{candidate function [with T = <>] not viable: requires 1 argument, but 2 were provided}} + // expected-note@#cwg1388-g {{candidate function [with T = <>] not viable: requires 1 argument, but 2 were provided}} g<>(0); g(0); // expected-error@-1 {{no matching function for call to 'g'}} - // expected-note@#dr1388-g {{candidate function [with T = ] not viable: requires 2 arguments, but 1 was provided}} + // expected-note@#cwg1388-g {{candidate function [with T = ] not viable: requires 2 arguments, but 1 was provided}} g(0, 0); h(0); h(0, 0); // expected-error@-1 {{no matching function for call to 'h'}} - // expected-note@#dr1388-h {{candidate function [with T = <>, A = int] not viable: requires 1 argument, but 2 were provided}} + // expected-note@#cwg1388-h {{candidate function [with T = <>, A = int] not viable: requires 1 argument, but 2 were provided}} h(0, 0); h(0, 0); // expected-error@-1 {{no matching function for call to 'h'}} - // expected-note@#dr1388-h {{candidate template ignored: couldn't infer template argument 'A'}} + // expected-note@#cwg1388-h {{candidate template ignored: couldn't infer template argument 'A'}} } // A non-trailing parameter pack is still a non-deduced context, even though @@ -570,40 +570,40 @@ namespace dr1388 { // dr1388: 4 template struct pair {}; template struct tuple { typedef char type; }; // // cxx98-error@-1 {{variadic templates are a C++11 extension}} - template void f_pair_1(pair..., int); // #dr1388-f-1 + template void f_pair_1(pair..., int); // #cwg1388-f-1 // cxx98-error@-1 {{variadic templates are a C++11 extension}} // cxx98-error@-2 {{variadic templates are a C++11 extension}} template void f_pair_2(pair..., U); // cxx98-error@-1 {{variadic templates are a C++11 extension}} - template void f_pair_3(pair..., tuple); // #dr1388-f-3 + template void f_pair_3(pair..., tuple); // #cwg1388-f-3 // cxx98-error@-1 {{variadic templates are a C++11 extension}} // cxx98-error@-2 {{variadic templates are a C++11 extension}} - template void f_pair_4(pair..., T...); // #dr1388-f-4 + template void f_pair_4(pair..., T...); // #cwg1388-f-4 // cxx98-error@-1 {{variadic templates are a C++11 extension}} void g(pair a, pair b, tuple c) { f_pair_1(a, b, 0); // expected-error@-1 {{no matching function for call to 'f_pair_1'}} - // expected-note@#dr1388-f-1 {{candidate template ignored: substitution failure [with T = ]: deduced incomplete pack <(no value), (no value)> for template parameter 'U'}} + // expected-note@#cwg1388-f-1 {{candidate template ignored: substitution failure [with T = ]: deduced incomplete pack <(no value), (no value)> for template parameter 'U'}} f_pair_2(a, b, 0); f_pair_3(a, b, c); f_pair_3(a, b, tuple()); // expected-error@-1 {{no matching function for call to 'f_pair_3'}} - // expected-note@#dr1388-f-3 {{candidate template ignored: deduced packs of different lengths for parameter 'U' (<(no value), (no value)> vs. )}} + // expected-note@#cwg1388-f-3 {{candidate template ignored: deduced packs of different lengths for parameter 'U' (<(no value), (no value)> vs. )}} f_pair_4(a, b, 0, 0L); f_pair_4(a, b, 0, 0L, "foo"); // expected-error@-1 {{no matching function for call to 'f_pair_4'}} - // expected-note@#dr1388-f-4 {{candidate template ignored: deduced packs of different lengths for parameter 'T' ( vs. )}} + // expected-note@#cwg1388-f-4 {{candidate template ignored: deduced packs of different lengths for parameter 'T' ( vs. )}} } } -namespace dr1391 { // dr1391: partial +namespace cwg1391 { // cwg1391: partial struct A {}; struct B : A {}; - template struct C { C(int); typename T::error error; }; // #dr1391-C - // expected-error@#dr1391-C {{type 'int' cannot be used prior to '::' because it has no members}} - // expected-note@#dr1391-b {{in instantiation of template class 'dr1391::C' requested here}} - // expected-note@#dr1391-b {{while substituting deduced template arguments into function template 'b' [with T = int]}} - // expected-error@#dr1391-C {{type 'double' cannot be used prior to '::' because it has no members}} - // expected-note@#dr1391-c {{in instantiation of template class 'dr1391::C' requested here}} + template struct C { C(int); typename T::error error; }; // #cwg1391-C + // expected-error@#cwg1391-C {{type 'int' cannot be used prior to '::' because it has no members}} + // expected-note@#cwg1391-b {{in instantiation of template class 'cwg1391::C' requested here}} + // expected-note@#cwg1391-b {{while substituting deduced template arguments into function template 'b' [with T = int]}} + // expected-error@#cwg1391-C {{type 'double' cannot be used prior to '::' because it has no members}} + // expected-note@#cwg1391-c {{in instantiation of template class 'cwg1391::C' requested here}} template struct D {}; // No deduction is performed for parameters with no deducible template-parameters, therefore types do not need to match. @@ -644,42 +644,42 @@ namespace dr1391 { // dr1391: partial void test_b() { b(0, 0); // ok, deduction fails prior to forming a conversion sequence and instantiating C // FIXME: The "while substituting" note should point at the overload candidate. - b(0, 0); // #dr1391-b + b(0, 0); // #cwg1391-b } template struct Id { typedef T type; }; template void c(T, typename Id >::type); void test_c() { // Implicit conversion sequences for dependent types are checked later. - c(0.0, 0); // #dr1391-c + c(0.0, 0); // #cwg1391-c } namespace partial_ordering { // FIXME: Second template should be considered more specialized because non-dependent parameter is ignored. - template int a(T, short) = delete; // #dr1391-a-short + template int a(T, short) = delete; // #cwg1391-a-short // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} - template int a(T*, char); // #dr1391-a-char + template int a(T*, char); // #cwg1391-a-char int test_a = a((int*)0, 0); // expected-error@-1 {{call to 'a' is ambiguous}} FIXME - // expected-note@#dr1391-a-short {{candidate function [with T = int *] has been explicitly deleted}} - // expected-note@#dr1391-a-char {{candidate function [with T = int]}} + // expected-note@#cwg1391-a-short {{candidate function [with T = int *] has been explicitly deleted}} + // expected-note@#cwg1391-a-char {{candidate function [with T = int]}} // FIXME: Second template should be considered more specialized: // deducing #1 from #2 ignores the second P/A pair, so deduction succeeds, // deducing #2 from #1 fails to deduce T, so deduction fails. - template int b(T, int) = delete; // #dr1391-b-int + template int b(T, int) = delete; // #cwg1391-b-int // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} - template int b(T*, U); // #dr1391-b-U + template int b(T*, U); // #cwg1391-b-U int test_b = b((int*)0, 0); // expected-error@-1 {{call to 'b' is ambiguous}} FIXME - // expected-note@#dr1391-b-int {{candidate function [with T = int *] has been explicitly deleted}} - // expected-note@#dr1391-b-U {{candidate function [with T = int, U = int]}} + // expected-note@#cwg1391-b-int {{candidate function [with T = int *] has been explicitly deleted}} + // expected-note@#cwg1391-b-U {{candidate function [with T = int, U = int]}} // Unintended consequences: because partial ordering does not consider // explicit template arguments, and deduction from a non-dependent type // vacuously succeeds, a non-dependent template is less specialized than // anything else! - // According to DR1391, this is ambiguous! + // According to CWG1391, this is ambiguous! template int c(int); template int c(T); int test_c1 = c(0); // ok @@ -687,46 +687,46 @@ namespace dr1391 { // dr1391: partial } } -namespace dr1394 { // dr1394: 15 +namespace cwg1394 { // cwg1394: 15 #if __cplusplus >= 201103L struct Incomplete; Incomplete f(Incomplete) = delete; // well-formed #endif } -namespace dr1395 { // dr1395: 16 +namespace cwg1395 { // cwg1395: 16 #if __cplusplus >= 201103L template void f(T, U...); template void f(T); void h(int i) { - // This is made ambiguous by dr692, but made valid again by dr1395. + // This is made ambiguous by cwg692, but made valid again by cwg1395. f(&i); } #endif } -namespace dr1397 { // dr1397: 3.2 +namespace cwg1397 { // cwg1397: 3.2 #if __cplusplus >= 201103L struct A { // cxx11-error@-1 {{default member initializer for 'p' needed within definition of enclosing class 'A' outside of member functions}} -// cxx11-note@#dr1397-p {{in evaluation of exception specification for 'dr1397::A::A' needed here}} -// cxx11-note@#dr1397-p {{default member initializer declared here}} - void *p = A{}; // #dr1397-p +// cxx11-note@#cwg1397-p {{in evaluation of exception specification for 'cwg1397::A::A' needed here}} +// cxx11-note@#cwg1397-p {{default member initializer declared here}} + void *p = A{}; // #cwg1397-p // since-cxx14-error@-1 {{default member initializer for 'p' needed within definition of enclosing class 'A' outside of member functions}} // since-cxx14-note@-2 {{default member initializer declared here}} operator void*() const { return nullptr; } }; #endif -} // namespace dr1397 +} // namespace cwg1397 -namespace dr1399 { // dr1399: dup 1388 - template void f(T..., int, T...) {} // #dr1399-f +namespace cwg1399 { // cwg1399: dup 1388 + template void f(T..., int, T...) {} // #cwg1399-f // cxx98-error@-1 {{variadic templates are a C++11 extension}} void g() { f(0); f(0, 0, 0); f(0, 0, 0); // expected-error@-1 {{no matching function for call to 'f'}} - // expected-note@#dr1399-f {{candidate template ignored: deduced packs of different lengths for parameter 'T' (<> vs. )}} + // expected-note@#cwg1399-f {{candidate template ignored: deduced packs of different lengths for parameter 'T' (<> vs. )}} } } diff --git a/clang/test/CXX/drs/dr14xx.cpp b/clang/test/CXX/drs/dr14xx.cpp index ed6dda731fd5187b96191e1fc73f45250cae0a3b..9ff9a68dc13c3059cb452c9cfea5964635277f5f 100644 --- a/clang/test/CXX/drs/dr14xx.cpp +++ b/clang/test/CXX/drs/dr14xx.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors -namespace dr1413 { // dr1413: 12 +namespace cwg1413 { // cwg1413: 12 template struct Check { typedef int type; }; @@ -21,28 +21,28 @@ namespace dr1413 { // dr1413: 12 // expected-error@-1 {{use of undeclared identifier 'var1'}} // ok, variable declaration - Check::type *var2; // #dr1413-var2 + Check::type *var2; // #cwg1413-var2 Check::type *var3; // expected-error@-1 {{use of undeclared identifier 'var3'}} - // expected-note@#dr1413-var2 {{'var2' declared here}} + // expected-note@#cwg1413-var2 {{'var2' declared here}} Check::type *var4; // expected-error@-1 {{use of undeclared identifier 'var4'}} - // expected-note@#dr1413-var2 {{'var2' declared here}} + // expected-note@#cwg1413-var2 {{'var2' declared here}} // value-dependent because of the implied type-dependent 'this->', not because of 'd' Check::type *var5; // expected-error@-1 {{use of undeclared identifier 'var5'}} - // expected-note@#dr1413-var2 {{'var2' declared here}} + // expected-note@#cwg1413-var2 {{'var2' declared here}} // value-dependent because of the value-dependent '&' operator, not because of 'A::d' Check::type *var5; // expected-error@-1 {{use of undeclared identifier 'var5'}} - // expected-note@#dr1413-var2 {{'var2' declared here}} + // expected-note@#cwg1413-var2 {{'var2' declared here}} } }; } -namespace dr1423 { // dr1423: 11 +namespace cwg1423 { // cwg1423: 11 #if __cplusplus >= 201103L bool b1 = nullptr; // since-cxx11-error@-1 {{cannot initialize a variable of type 'bool' with an rvalue of type 'std::nullptr_t'}} @@ -55,9 +55,9 @@ namespace dr1423 { // dr1423: 11 #endif } -// dr1425: na abi +// cwg1425: na abi -namespace dr1432 { // dr1432: 16 +namespace cwg1432 { // cwg1432: 16 #if __cplusplus >= 201103L template T declval(); @@ -78,7 +78,7 @@ namespace dr1432 { // dr1432: 16 #endif } -namespace dr1443 { // dr1443: yes +namespace cwg1443 { // cwg1443: yes struct A { int i; A() { void foo(int=i); } @@ -86,7 +86,7 @@ struct A { }; } -namespace dr1460 { // dr1460: 3.5 +namespace cwg1460 { // cwg1460: 3.5 #if __cplusplus >= 201103L namespace DRExample { union A { @@ -121,23 +121,23 @@ namespace dr1460 { // dr1460: 3.5 } union A {}; - union B { int n; }; // #dr1460-B + union B { int n; }; // #cwg1460-B union C { int n = 0; }; struct D { union {}; }; // expected-error@-1 {{declaration does not declare anything}} - struct E { union { int n; }; }; // #dr1460-E + struct E { union { int n; }; }; // #cwg1460-E struct F { union { int n = 0; }; }; struct X { friend constexpr A::A() noexcept; friend constexpr B::B() noexcept; // cxx11-17-error@-1 {{constexpr declaration of 'B' follows non-constexpr declaration}} - // cxx11-17-note@#dr1460-B {{previous declaration is here}} + // cxx11-17-note@#cwg1460-B {{previous declaration is here}} friend constexpr C::C() noexcept; friend constexpr D::D() noexcept; friend constexpr E::E() noexcept; // cxx11-17-error@-1 {{constexpr declaration of 'E' follows non-constexpr declaration}} - // cxx11-17-note@#dr1460-E {{previous declaration is here}} + // cxx11-17-note@#cwg1460-E {{previous declaration is here}} friend constexpr F::F() noexcept; }; @@ -167,63 +167,63 @@ namespace dr1460 { // dr1460: 3.5 union { int n = 0; }; - union { // #dr1460-H-union + union { // #cwg1460-H-union int m; }; constexpr H() {} // cxx11-17-error@-1 {{constexpr constructor that does not initialize all members is a C++20 extension}} - // cxx11-17-note@#dr1460-H-union {{member not initialized by constructor}} + // cxx11-17-note@#cwg1460-H-union {{member not initialized by constructor}} constexpr H(bool) : m(1) {} constexpr H(char) : n(1) {} // cxx11-17-error@-1 {{constexpr constructor that does not initialize all members is a C++20 extension}} - // cxx11-17-note@#dr1460-H-union {{member not initialized by constructor}} + // cxx11-17-note@#cwg1460-H-union {{member not initialized by constructor}} constexpr H(double) : m(1), n(1) {} }; } #if __cplusplus >= 201403L template constexpr bool check() { - T t; // #dr1460-t + T t; // #cwg1460-t return true; } static_assert(check(), ""); - static_assert(check(), ""); // #dr1460-check-B + static_assert(check(), ""); // #cwg1460-check-B // cxx14-17-error@-1 {{static assertion expression is not an integral constant expression}} - // cxx14-17-note@#dr1460-t {{non-constexpr constructor 'B' cannot be used in a constant expression}} - // cxx14-17-note@#dr1460-check-B {{in call to 'check()'}} - // cxx14-17-note@#dr1460-B {{declared here}} + // cxx14-17-note@#cwg1460-t {{non-constexpr constructor 'B' cannot be used in a constant expression}} + // cxx14-17-note@#cwg1460-check-B {{in call to 'check()'}} + // cxx14-17-note@#cwg1460-B {{declared here}} static_assert(check(), ""); static_assert(check(), ""); - static_assert(check(), ""); // #dr1460-check-E + static_assert(check(), ""); // #cwg1460-check-E // cxx14-17-error@-1 {{static assertion expression is not an integral constant expression}} - // cxx14-17-note@#dr1460-t {{non-constexpr constructor 'E' cannot be used in a constant expression}} - // cxx14-17-note@#dr1460-check-E {{in call to 'check()'}} - // cxx14-17-note@#dr1460-E {{declared here}} + // cxx14-17-note@#cwg1460-t {{non-constexpr constructor 'E' cannot be used in a constant expression}} + // cxx14-17-note@#cwg1460-check-E {{in call to 'check()'}} + // cxx14-17-note@#cwg1460-E {{declared here}} static_assert(check(), ""); #endif union G { - int a = 0; // #dr1460-G-a + int a = 0; // #cwg1460-G-a int b = 0; // expected-error@-1 {{initializing multiple members of union}} - // expected-note@#dr1460-G-a {{previous initialization is here}} + // expected-note@#cwg1460-G-a {{previous initialization is here}} }; union H { union { - int a = 0; // #dr1460-H-a + int a = 0; // #cwg1460-H-a }; union { int b = 0; // expected-error@-1 {{initializing multiple members of union}} - // expected-note@#dr1460-H-a {{previous initialization is here}} + // expected-note@#cwg1460-H-a {{previous initialization is here}} }; }; struct I { union { - int a = 0; // #dr1460-I-a + int a = 0; // #cwg1460-I-a int b = 0; // expected-error@-1 {{initializing multiple members of union}} - // expected-note@#dr1460-I-a {{previous initialization is here}} + // expected-note@#cwg1460-I-a {{previous initialization is here}} }; }; struct J { @@ -374,9 +374,9 @@ namespace std { } // std #endif -namespace dr1467 { // dr1467: 3.7 c++11 +namespace cwg1467 { // cwg1467: 3.7 c++11 #if __cplusplus >= 201103L - // Note that the change to [over.best.ics] was partially undone by DR2076; + // Note that the change to [over.best.ics] was partially undone by CWG2076; // the resulting rule is tested with the tests for that change. // List-initialization of aggregate from same-type object @@ -441,12 +441,12 @@ namespace dr1467 { // dr1467: 3.7 c++11 X x; X x2{x}; - void f1(int); // #dr1467-f1 - void f1(std::initializer_list) = delete; // #dr1467-f1-deleted + void f1(int); // #cwg1467-f1 + void f1(std::initializer_list) = delete; // #cwg1467-f1-deleted void g1() { f1({42}); } // since-cxx11-error@-1 {{call to deleted function 'f1'}} - // since-cxx11-note@#dr1467-f1 {{candidate function}} - // since-cxx11-note@#dr1467-f1-deleted {{candidate function has been explicitly deleted}} + // since-cxx11-note@#cwg1467-f1 {{candidate function}} + // since-cxx11-note@#cwg1467-f1-deleted {{candidate function has been explicitly deleted}} template struct Pair { @@ -456,12 +456,12 @@ namespace dr1467 { // dr1467: 3.7 c++11 String(const char *); }; - void f2(Pair); // #dr1467-f2 - void f2(std::initializer_list) = delete; // #dr1467-f2-deleted + void f2(Pair); // #cwg1467-f2 + void f2(std::initializer_list) = delete; // #cwg1467-f2-deleted void g2() { f2({"foo", "bar"}); } // since-cxx11-error@-1 {{call to deleted function 'f2'}} - // since-cxx11-note@#dr1467-f2 {{candidate function}} - // since-cxx11-note@#dr1467-f2-deleted {{candidate function has been explicitly deleted}} + // since-cxx11-note@#cwg1467-f2 {{candidate function}} + // since-cxx11-note@#cwg1467-f2-deleted {{candidate function has been explicitly deleted}} } // dr_example namespace nonaggregate { @@ -522,88 +522,88 @@ namespace dr1467 { // dr1467: 3.7 c++11 // When the array size is 4 the call will attempt to bind an lvalue to an // rvalue and fail. Therefore #2 will be called. (rsmith will bring this // issue to CWG) - void f(const char(&&)[4]); // #dr1467-f-char-4 - void f(const char(&&)[5]) = delete; // #dr1467-f-char-5 - void f(const wchar_t(&&)[4]); // #dr1467-f-wchar-4 - void f(const wchar_t(&&)[5]) = delete; // #dr1467-f-wchar-5 + void f(const char(&&)[4]); // #cwg1467-f-char-4 + void f(const char(&&)[5]) = delete; // #cwg1467-f-char-5 + void f(const wchar_t(&&)[4]); // #cwg1467-f-wchar-4 + void f(const wchar_t(&&)[5]) = delete; // #cwg1467-f-wchar-5 #if __cplusplus >= 202002L - void f2(const char8_t(&&)[4]); // #dr1467-f2-char8-4 - void f2(const char8_t(&&)[5]) = delete; // #dr1467-f2-char8-5 + void f2(const char8_t(&&)[4]); // #cwg1467-f2-char8-4 + void f2(const char8_t(&&)[5]) = delete; // #cwg1467-f2-char8-5 #endif - void f(const char16_t(&&)[4]); // #dr1467-f-char16-4 - void f(const char16_t(&&)[5]) = delete; // #dr1467-f-char16-5 - void f(const char32_t(&&)[4]); // #dr1467-f-char32-4 - void f(const char32_t(&&)[5]) = delete; // #dr1467-f-char32-5 + void f(const char16_t(&&)[4]); // #cwg1467-f-char16-4 + void f(const char16_t(&&)[5]) = delete; // #cwg1467-f-char16-5 + void f(const char32_t(&&)[4]); // #cwg1467-f-char32-4 + void f(const char32_t(&&)[5]) = delete; // #cwg1467-f-char32-5 void g() { f({"abc"}); // since-cxx11-error@-1 {{call to deleted function 'f'}} - // since-cxx11-note@#dr1467-f-char-5 {{candidate function has been explicitly deleted}} - // since-cxx11-note@#dr1467-f-char-4 {{candidate function not viable: expects an rvalue for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char-5 {{candidate function has been explicitly deleted}} + // since-cxx11-note@#cwg1467-f-char-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} f({((("abc")))}); // since-cxx11-error@-1 {{call to deleted function 'f'}} - // since-cxx11-note@#dr1467-f-char-5 {{candidate function has been explicitly deleted}} - // since-cxx11-note@#dr1467-f-char-4 {{candidate function not viable: expects an rvalue for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char-5 {{candidate function has been explicitly deleted}} + // since-cxx11-note@#cwg1467-f-char-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} f({L"abc"}); // since-cxx11-error@-1 {{call to deleted function 'f'}} - // since-cxx11-note@#dr1467-f-wchar-5 {{candidate function has been explicitly deleted}} - // since-cxx11-note@#dr1467-f-char-4 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char' for 1st argument}} - // since-cxx11-note@#dr1467-f-char-5 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char' for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-4 {{candidate function not viable: expects an rvalue for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-4 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-5 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-4 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char32_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-5 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-5 {{candidate function has been explicitly deleted}} + // since-cxx11-note@#cwg1467-f-char-4 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char-5 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-4 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-5 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-4 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-5 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char32_t' for 1st argument}} #if __cplusplus >= 202002L f2({u8"abc"}); // since-cxx20-error@-1 {{call to deleted function 'f2'}} - // since-cxx20-note@#dr1467-f2-char8-5 {{candidate function has been explicitly deleted}} - // since-cxx20-note@#dr1467-f2-char8-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx20-note@#cwg1467-f2-char8-5 {{candidate function has been explicitly deleted}} + // since-cxx20-note@#cwg1467-f2-char8-4 {{candidate function not viable: expects an rvalue for 1st argument}} #endif f({uR"(abc)"}); // since-cxx11-error@-1 {{call to deleted function 'f'}} - // since-cxx11-note@#dr1467-f-char16-5 {{candidate function has been explicitly deleted}} - // since-cxx11-note@#dr1467-f-char-4 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char' for 1st argument}} - // since-cxx11-note@#dr1467-f-char-5 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char' for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-4 {{candidate function not viable: expects an rvalue for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-4 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char32_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-5 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-5 {{candidate function has been explicitly deleted}} + // since-cxx11-note@#cwg1467-f-char-4 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char-5 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-4 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-5 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char32_t' for 1st argument}} f({(UR"(abc)")}); // since-cxx11-error@-1 {{call to deleted function 'f'}} - // since-cxx11-note@#dr1467-f-char32-5 {{candidate function has been explicitly deleted}} - // since-cxx11-note@#dr1467-f-char-4 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char' for 1st argument}} - // since-cxx11-note@#dr1467-f-char-5 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char' for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const wchar_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-4 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char16-5 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char16_t' for 1st argument}} - // since-cxx11-note@#dr1467-f-char32-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-5 {{candidate function has been explicitly deleted}} + // since-cxx11-note@#cwg1467-f-char-4 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char-5 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-4 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char16-5 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#cwg1467-f-char32-4 {{candidate function not viable: expects an rvalue for 1st argument}} } } // namespace StringLiterals #endif -} // dr1467 +} // cwg1467 -namespace dr1479 { // dr1479: 3.1 +namespace cwg1479 { // cwg1479: 3.1 #if __cplusplus >= 201103L int operator"" _a(const char*, std::size_t = 0); // since-cxx11-error@-1 {{literal operator cannot have a default argument}} #endif } -namespace dr1482 { // dr1482: 3.0 +namespace cwg1482 { // cwg1482: 3.0 // NB: sup 2516, test reused there #if __cplusplus >= 201103L template struct S { @@ -612,11 +612,11 @@ template struct S { enum E2 : S::I { e }; // since-cxx11-error@-1 {{use of undeclared identifier 'E2'}} #endif -} // namespace dr1482 +} // namespace cwg1482 -namespace dr1487 { // dr1487: 3.3 +namespace cwg1487 { // cwg1487: 3.3 #if __cplusplus >= 201103L -struct A { // #dr1482-A +struct A { // #cwg1482-A struct B { using A::A; // since-cxx11-error@-1 {{using declaration refers into 'A::', which is not a base class of 'B'}} @@ -624,7 +624,7 @@ struct A { // #dr1482-A struct C : A { // since-cxx11-error@-1 {{base class has incomplete type}} - // since-cxx11-note@#dr1482-A {{definition of 'dr1487::A' is not complete until the closing '}'}} + // since-cxx11-note@#cwg1482-A {{definition of 'cwg1487::A' is not complete until the closing '}'}} using A::A; // since-cxx11-error@-1 {{using declaration refers into 'A::', which is not a base class of 'C'}} }; @@ -636,9 +636,9 @@ struct D : A { using A::A; }; #endif -} // namespace dr1487 +} // namespace cwg1487 -namespace dr1490 { // dr1490: 3.7 c++11 +namespace cwg1490 { // cwg1490: 3.7 c++11 #if __cplusplus >= 201103L // List-initialization from a string literal @@ -646,51 +646,51 @@ namespace dr1490 { // dr1490: 3.7 c++11 std::initializer_list{"abc"}; // since-cxx11-error@-1 {{expected unqualified-id}}} #endif -} // dr1490 +} // cwg1490 -namespace dr1495 { // dr1495: 4 +namespace cwg1495 { // cwg1495: 4 #if __cplusplus >= 201103L // Deduction succeeds in both directions. - template struct A {}; // #dr1495-A + template struct A {}; // #cwg1495-A template struct A {}; // since-cxx11-error@-1 {{class template partial specialization is not more specialized than the primary template}} - // since-cxx11-note@#dr1495-A {{template is declared here}} + // since-cxx11-note@#cwg1495-A {{template is declared here}} // Primary template is more specialized. - template struct B {}; // #dr1495-B + template struct B {}; // #cwg1495-B template struct B {}; // since-cxx11-error@-1 {{class template partial specialization is not more specialized than the primary template}} - // since-cxx11-note@#dr1495-B {{template is declared here}} + // since-cxx11-note@#cwg1495-B {{template is declared here}} // Deduction fails in both directions. - template struct C {}; // #dr1495-C + template struct C {}; // #cwg1495-C template struct C<0, Ts...> {}; // since-cxx11-error@-1 {{class template partial specialization is not more specialized than the primary template}} - // since-cxx11-note@#dr1495-C {{template is declared here}} + // since-cxx11-note@#cwg1495-C {{template is declared here}} #if __cplusplus >= 201402L // Deduction succeeds in both directions. - template int a; // #dr1495-a + template int a; // #cwg1495-a template int a; // since-cxx14-error@-1 {{variable template partial specialization is not more specialized than the primary template}} - // since-cxx14-note@#dr1495-a {{template is declared here}} + // since-cxx14-note@#cwg1495-a {{template is declared here}} // Primary template is more specialized. - template int b; // #dr1495-b + template int b; // #cwg1495-b template int b; // since-cxx14-error@-1 {{variable template partial specialization is not more specialized than the primary template}} - // since-cxx14-note@#dr1495-b {{template is declared here}} + // since-cxx14-note@#cwg1495-b {{template is declared here}} // Deduction fails in both directions. - template int c; // #dr1495-c + template int c; // #cwg1495-c template int c<0, Ts...>; // since-cxx14-error@-1 {{variable template partial specialization is not more specialized than the primary template}} - // since-cxx14-note@#dr1495-c {{template is declared here}} + // since-cxx14-note@#cwg1495-c {{template is declared here}} #endif #endif } -namespace dr1496 { // dr1496: no +namespace cwg1496 { // cwg1496: no #if __cplusplus >= 201103L struct A { A() = delete; diff --git a/clang/test/CXX/drs/dr15xx.cpp b/clang/test/CXX/drs/dr15xx.cpp index 195c0fa610d579fc1bf041363694bf902ec222fe..21a392a5141e3f2ba6573bcb49432fa0c4216b7e 100644 --- a/clang/test/CXX/drs/dr15xx.cpp +++ b/clang/test/CXX/drs/dr15xx.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors -namespace dr1512 { // dr1512: 4 +namespace cwg1512 { // cwg1512: 4 void f(char *p) { if (p > 0) {} // expected-error@-1 {{ordered comparison between pointer and zero ('char *' and 'int')}} @@ -33,11 +33,11 @@ namespace dr1512 { // dr1512: 4 template void composite_pointer_type_is_ord() { composite_pointer_type_is_base(); - typedef __typeof(val() < val()) cmp; // #dr1512-lt - // since-cxx17-warning@#dr1512-lt {{ordered comparison of function pointers ('int (*)() noexcept' and 'int (*)()')}} - // since-cxx17-note@#dr1512-noexcept-1st {{in instantiation of function template specialization 'dr1512::composite_pointer_type_is_ord' requested here}} - // since-cxx17-warning@#dr1512-lt {{ordered comparison of function pointers ('int (*)()' and 'int (*)() noexcept')}} - // since-cxx17-note@#dr1512-noexcept-2nd {{in instantiation of function template specialization 'dr1512::composite_pointer_type_is_ord' requested here}} + typedef __typeof(val() < val()) cmp; // #cwg1512-lt + // since-cxx17-warning@#cwg1512-lt {{ordered comparison of function pointers ('int (*)() noexcept' and 'int (*)()')}} + // since-cxx17-note@#cwg1512-noexcept-1st {{in instantiation of function template specialization 'cwg1512::composite_pointer_type_is_ord' requested here}} + // since-cxx17-warning@#cwg1512-lt {{ordered comparison of function pointers ('int (*)()' and 'int (*)() noexcept')}} + // since-cxx17-note@#cwg1512-noexcept-2nd {{in instantiation of function template specialization 'cwg1512::composite_pointer_type_is_ord' requested here}} typedef __typeof(val() <= val()) cmp; // since-cxx17-warning@-1 {{ordered comparison of function pointers ('int (*)() noexcept' and 'int (*)()')}} // since-cxx17-warning@-2 {{ordered comparison of function pointers ('int (*)()' and 'int (*)() noexcept')}} @@ -95,8 +95,8 @@ namespace dr1512 { // dr1512: 4 // since-cxx20-warning@-1 {{volatile-qualified return type 'volatile int' is deprecated}} #if __cplusplus >= 201703L - composite_pointer_type_is_ord(); // #dr1512-noexcept-1st - composite_pointer_type_is_ord(); // #dr1512-noexcept-2nd + composite_pointer_type_is_ord(); // #cwg1512-noexcept-1st + composite_pointer_type_is_ord(); // #cwg1512-noexcept-2nd composite_pointer_type_is_unord(); composite_pointer_type_is_unord(); // FIXME: This looks like a standard defect; these should probably all have type 'int (B::*)()'. @@ -129,7 +129,7 @@ namespace dr1512 { // dr1512: 4 } #if __cplusplus >= 201103L - template struct Wrap { operator T(); }; // #dr1512-Wrap + template struct Wrap { operator T(); }; // #cwg1512-Wrap void test_overload() { using nullptr_t = decltype(nullptr); void(Wrap() == Wrap()); @@ -143,75 +143,75 @@ namespace dr1512 { // dr1512: 4 void(Wrap() >= Wrap()); // since-cxx11-error@-1 {{invalid operands to binary expression ('Wrap' (aka 'Wrap') and 'Wrap' (aka 'Wrap'))}} - // Under dr1213, this is ill-formed: we select the builtin operator<(int*, int*) + // Under cwg1213, this is ill-formed: we select the builtin operator<(int*, int*) // but then only convert as far as 'nullptr_t', which we then can't convert to 'int*'. void(Wrap() == Wrap()); void(Wrap() != Wrap()); void(Wrap() < Wrap()); // since-cxx11-error@-1 {{invalid operands to binary expression ('Wrap' (aka 'Wrap') and 'Wrap')}} - // since-cxx11-note@#dr1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} - // since-cxx11-note@#dr1512-Wrap {{second operand was implicitly converted to type 'int *'}} + // since-cxx11-note@#cwg1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} + // since-cxx11-note@#cwg1512-Wrap {{second operand was implicitly converted to type 'int *'}} void(Wrap() > Wrap()); // since-cxx11-error@-1 {{invalid operands}} - // since-cxx11-note@#dr1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} - // since-cxx11-note@#dr1512-Wrap{{second operand was implicitly converted to type 'int *'}} + // since-cxx11-note@#cwg1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} + // since-cxx11-note@#cwg1512-Wrap{{second operand was implicitly converted to type 'int *'}} void(Wrap() <= Wrap()); // since-cxx11-error@-1 {{invalid operands}} - // since-cxx11-note@#dr1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} - // since-cxx11-note@#dr1512-Wrap {{second operand was implicitly converted to type 'int *'}} + // since-cxx11-note@#cwg1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} + // since-cxx11-note@#cwg1512-Wrap {{second operand was implicitly converted to type 'int *'}} void(Wrap() >= Wrap()); // since-cxx11-error@-1 {{invalid operands}} - // since-cxx11-note@#dr1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} - // since-cxx11-note@#dr1512-Wrap {{second operand was implicitly converted to type 'int *'}} + // since-cxx11-note@#cwg1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} + // since-cxx11-note@#cwg1512-Wrap {{second operand was implicitly converted to type 'int *'}} } #endif } -namespace dr1514 { // dr1514: 11 +namespace cwg1514 { // cwg1514: 11 #if __cplusplus >= 201103L struct S { - enum E : int {}; // #dr1514-E + enum E : int {}; // #cwg1514-E enum E : int {}; // since-cxx11-error@-1 {{redefinition of 'E'}} - // since-cxx11-note@#dr1514-E {{previous definition is here}} + // since-cxx11-note@#cwg1514-E {{previous definition is here}} }; S::E se; // OK, complete type, not zero-width bitfield. - // The behavior in other contexts is superseded by DR1966. + // The behavior in other contexts is superseded by CWG1966. #endif } -namespace dr1518 { // dr1518: 4 +namespace cwg1518 { // cwg1518: 4 #if __cplusplus >= 201103L -struct Z0 { // #dr1518-Z0 - explicit Z0() = default; // #dr1518-Z0-ctor +struct Z0 { // #cwg1518-Z0 + explicit Z0() = default; // #cwg1518-Z0-ctor }; -struct Z { // #dr1518-Z - explicit Z(); // #dr1518-Z-ctor - explicit Z(int); // #dr1518-Z-int - explicit Z(int, int); // #dr1518-Z-int-int +struct Z { // #cwg1518-Z + explicit Z(); // #cwg1518-Z-ctor + explicit Z(int); // #cwg1518-Z-int + explicit Z(int, int); // #cwg1518-Z-int-int }; -template int Eat(T); // #dr1518-Eat +template int Eat(T); // #cwg1518-Eat Z0 a; Z0 b{}; Z0 c = {}; // since-cxx11-error@-1 {{chosen constructor is explicit in copy-initialization}} -// since-cxx11-note@#dr1518-Z0-ctor {{explicit constructor declared here}} +// since-cxx11-note@#cwg1518-Z0-ctor {{explicit constructor declared here}} int i = Eat({}); // since-cxx11-error@-1 {{no matching function for call to 'Eat'}} -// since-cxx11-note@#dr1518-Eat {{candidate function template not viable: cannot convert initializer list argument to 'Z0'}} +// since-cxx11-note@#cwg1518-Eat {{candidate function template not viable: cannot convert initializer list argument to 'Z0'}} Z c2 = {}; // since-cxx11-error@-1 {{chosen constructor is explicit in copy-initialization}} -// since-cxx11-note@#dr1518-Z-ctor {{explicit constructor declared here}} +// since-cxx11-note@#cwg1518-Z-ctor {{explicit constructor declared here}} int i2 = Eat({}); // since-cxx11-error@-1 {{no matching function for call to 'Eat'}} -// since-cxx11-note@#dr1518-Eat {{candidate function template not viable: cannot convert initializer list argument to 'Z'}} +// since-cxx11-note@#cwg1518-Eat {{candidate function template not viable: cannot convert initializer list argument to 'Z'}} Z a1 = 1; // since-cxx11-error@-1 {{no viable conversion from 'int' to 'Z'}} -// since-cxx11-note@#dr1518-Z {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const Z &' for 1st argument}} -// since-cxx11-note@#dr1518-Z {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'Z &&' for 1st argument}} -// since-cxx11-note@#dr1518-Z-int {{explicit constructor is not a candidate}} +// since-cxx11-note@#cwg1518-Z {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const Z &' for 1st argument}} +// since-cxx11-note@#cwg1518-Z {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'Z &&' for 1st argument}} +// since-cxx11-note@#cwg1518-Z-int {{explicit constructor is not a candidate}} Z a3 = Z(1); Z a2(1); Z *p = new Z(1); @@ -219,129 +219,129 @@ Z a4 = (Z)1; Z a5 = static_cast(1); Z a6 = {4, 3}; // since-cxx11-error@-1 {{chosen constructor is explicit in copy-initialization}} -// since-cxx11-note@#dr1518-Z-int-int {{explicit constructor declared here}} +// since-cxx11-note@#cwg1518-Z-int-int {{explicit constructor declared here}} -struct UserProvidedBaseCtor { // #dr1518-U +struct UserProvidedBaseCtor { // #cwg1518-U UserProvidedBaseCtor() {} }; -struct DoesntInheritCtor : UserProvidedBaseCtor { // #dr1518-D-U +struct DoesntInheritCtor : UserProvidedBaseCtor { // #cwg1518-D-U int x; }; DoesntInheritCtor I{{}, 42}; // cxx11-14-error@-1 {{no matching constructor for initialization of 'DoesntInheritCtor'}} -// cxx11-14-note@#dr1518-D-U {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} -// cxx11-14-note@#dr1518-D-U {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} -// cxx11-14-note@#dr1518-D-U {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided}} +// cxx11-14-note@#cwg1518-D-U {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} +// cxx11-14-note@#cwg1518-D-U {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} +// cxx11-14-note@#cwg1518-D-U {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided}} -struct BaseCtor { BaseCtor() = default; }; // #dr1518-BC -struct InheritsCtor : BaseCtor { // #dr1518-I - using BaseCtor::BaseCtor; // #dr1518-I-using +struct BaseCtor { BaseCtor() = default; }; // #cwg1518-BC +struct InheritsCtor : BaseCtor { // #cwg1518-I + using BaseCtor::BaseCtor; // #cwg1518-I-using int x; }; InheritsCtor II = {{}, 42}; // since-cxx11-error@-1 {{no matching constructor for initialization of 'InheritsCtor'}} -// since-cxx11-note@#dr1518-BC {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} -// since-cxx11-note@#dr1518-I-using {{constructor from base class 'BaseCtor' inherited here}} -// since-cxx11-note@#dr1518-BC {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} -// since-cxx11-note@#dr1518-I-using {{constructor from base class 'BaseCtor' inherited here}} -// since-cxx11-note@#dr1518-I {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} -// since-cxx11-note@#dr1518-I {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} -// since-cxx11-note@#dr1518-I {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided}} +// since-cxx11-note@#cwg1518-BC {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} +// since-cxx11-note@#cwg1518-I-using {{constructor from base class 'BaseCtor' inherited here}} +// since-cxx11-note@#cwg1518-BC {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} +// since-cxx11-note@#cwg1518-I-using {{constructor from base class 'BaseCtor' inherited here}} +// since-cxx11-note@#cwg1518-I {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} +// since-cxx11-note@#cwg1518-I {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} +// since-cxx11-note@#cwg1518-I {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided}} namespace std_example { struct A { - explicit A() = default; // #dr1518-A + explicit A() = default; // #cwg1518-A }; struct B : A { - explicit B() = default; // #dr1518-B + explicit B() = default; // #cwg1518-B }; struct C { - explicit C(); // #dr1518-C + explicit C(); // #cwg1518-C }; struct D : A { C c; - explicit D() = default; // #dr1518-D + explicit D() = default; // #cwg1518-D }; template void f() { T t; // ok T u{}; // ok - T v = {}; // #dr1518-v - // since-cxx11-error@#dr1518-v {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-f-A {{in instantiation of function template specialization 'dr1518::std_example::f' requested here}} - // since-cxx11-note@#dr1518-A {{explicit constructor declared here}} - // since-cxx11-error@#dr1518-v {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-f-B {{in instantiation of function template specialization 'dr1518::std_example::f' requested here}} - // since-cxx11-note@#dr1518-B {{explicit constructor declared here}} - // since-cxx11-error@#dr1518-v {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-f-C {{in instantiation of function template specialization 'dr1518::std_example::f' requested here}} - // since-cxx11-note@#dr1518-C {{explicit constructor declared here}} - // since-cxx11-error@#dr1518-v {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-f-D {{in instantiation of function template specialization 'dr1518::std_example::f' requested here}} - // since-cxx11-note@#dr1518-D {{explicit constructor declared here}} + T v = {}; // #cwg1518-v + // since-cxx11-error@#cwg1518-v {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-f-A {{in instantiation of function template specialization 'cwg1518::std_example::f' requested here}} + // since-cxx11-note@#cwg1518-A {{explicit constructor declared here}} + // since-cxx11-error@#cwg1518-v {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-f-B {{in instantiation of function template specialization 'cwg1518::std_example::f' requested here}} + // since-cxx11-note@#cwg1518-B {{explicit constructor declared here}} + // since-cxx11-error@#cwg1518-v {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-f-C {{in instantiation of function template specialization 'cwg1518::std_example::f' requested here}} + // since-cxx11-note@#cwg1518-C {{explicit constructor declared here}} + // since-cxx11-error@#cwg1518-v {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-f-D {{in instantiation of function template specialization 'cwg1518::std_example::f' requested here}} + // since-cxx11-note@#cwg1518-D {{explicit constructor declared here}} } template void g() { - void x(T t); // #dr1518-x - x({}); // #dr1518-x-call - // since-cxx11-error@#dr1518-x-call {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-g-A {{in instantiation of function template specialization 'dr1518::std_example::g' requested here}} - // since-cxx11-note@#dr1518-A {{explicit constructor declared here}} - // since-cxx11-note@#dr1518-x {{passing argument to parameter 't' here}} - // since-cxx11-error@#dr1518-x-call {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-g-B {{in instantiation of function template specialization 'dr1518::std_example::g' requested here}} - // since-cxx11-note@#dr1518-B {{explicit constructor declared here}} - // since-cxx11-note@#dr1518-x {{passing argument to parameter 't' here}} - // since-cxx11-error@#dr1518-x-call {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-g-C {{in instantiation of function template specialization 'dr1518::std_example::g' requested here}} - // since-cxx11-note@#dr1518-C {{explicit constructor declared here}} - // since-cxx11-note@#dr1518-x {{passing argument to parameter 't' here}} - // since-cxx11-error@#dr1518-x-call {{chosen constructor is explicit in copy-initialization}} - // since-cxx11-note@#dr1518-g-D {{in instantiation of function template specialization 'dr1518::std_example::g' requested here}} - // since-cxx11-note@#dr1518-D {{explicit constructor declared here}} - // since-cxx11-note@#dr1518-x {{passing argument to parameter 't' here}} + void x(T t); // #cwg1518-x + x({}); // #cwg1518-x-call + // since-cxx11-error@#cwg1518-x-call {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-g-A {{in instantiation of function template specialization 'cwg1518::std_example::g' requested here}} + // since-cxx11-note@#cwg1518-A {{explicit constructor declared here}} + // since-cxx11-note@#cwg1518-x {{passing argument to parameter 't' here}} + // since-cxx11-error@#cwg1518-x-call {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-g-B {{in instantiation of function template specialization 'cwg1518::std_example::g' requested here}} + // since-cxx11-note@#cwg1518-B {{explicit constructor declared here}} + // since-cxx11-note@#cwg1518-x {{passing argument to parameter 't' here}} + // since-cxx11-error@#cwg1518-x-call {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-g-C {{in instantiation of function template specialization 'cwg1518::std_example::g' requested here}} + // since-cxx11-note@#cwg1518-C {{explicit constructor declared here}} + // since-cxx11-note@#cwg1518-x {{passing argument to parameter 't' here}} + // since-cxx11-error@#cwg1518-x-call {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#cwg1518-g-D {{in instantiation of function template specialization 'cwg1518::std_example::g' requested here}} + // since-cxx11-note@#cwg1518-D {{explicit constructor declared here}} + // since-cxx11-note@#cwg1518-x {{passing argument to parameter 't' here}} } void test() { - f(); // #dr1518-f-A - f(); // #dr1518-f-B - f(); // #dr1518-f-C - f(); // #dr1518-f-D - g(); // #dr1518-g-A - g(); // #dr1518-g-B - g(); // #dr1518-g-C - g(); // #dr1518-g-D + f(); // #cwg1518-f-A + f(); // #cwg1518-f-B + f(); // #cwg1518-f-C + f(); // #cwg1518-f-D + g(); // #cwg1518-g-A + g(); // #cwg1518-g-B + g(); // #cwg1518-g-C + g(); // #cwg1518-g-D } } #endif // __cplusplus >= 201103L } -namespace dr1550 { // dr1550: 3.4 +namespace cwg1550 { // cwg1550: 3.4 int f(bool b, int n) { return (b ? (throw 0) : n) + (b ? n : (throw 0)); } } -namespace dr1558 { // dr1558: 12 +namespace cwg1558 { // cwg1558: 12 #if __cplusplus >= 201103L template using first_of = T; - template first_of f(int); // #dr1558-f - template void f(...) = delete; // #dr1558-f-deleted + template first_of f(int); // #cwg1558-f + template void f(...) = delete; // #cwg1558-f-deleted struct X { typedef void type; }; void test() { f(0); f(0); // since-cxx11-error@-1 {{call to deleted function 'f'}} - // since-cxx11-note@#dr1558-f-deleted {{candidate function [with T = int] has been explicitly deleted}} - // since-cxx11-note@#dr1558-f {{candidate template ignored: substitution failure [with T = int]: type 'int' cannot be used prior to '::' because it has no members}} + // since-cxx11-note@#cwg1558-f-deleted {{candidate function [with T = int] has been explicitly deleted}} + // since-cxx11-note@#cwg1558-f {{candidate template ignored: substitution failure [with T = int]: type 'int' cannot be used prior to '::' because it has no members}} } #endif } -namespace dr1560 { // dr1560: 3.5 +namespace cwg1560 { // cwg1560: 3.5 void f(bool b, int n) { (b ? throw 0 : n) = (b ? n : throw 0) = 0; } @@ -350,7 +350,7 @@ namespace dr1560 { // dr1560: 3.5 const X &x = true ? get() : throw 0; } -namespace dr1563 { // dr1563: yes +namespace cwg1563 { // cwg1563: yes #if __cplusplus >= 201103L double bar(double) { return 0.0; } float bar(float) { return 0.0f; } @@ -360,7 +360,7 @@ namespace dr1563 { // dr1563: yes #endif } -namespace dr1567 { // dr1567: 3.3 +namespace cwg1567 { // cwg1567: 3.3 #if __cplusplus >= 201103L struct B; struct A { @@ -368,12 +368,12 @@ struct A { A(const B&) = delete; A(A&&); A(B&&) = delete; - A(int); // #dr1567-A-int + A(int); // #cwg1567-A-int }; -struct B: A { // #dr1567-B - using A::A; // #dr1567-using-A - B(double); // #dr1567-B-double +struct B: A { // #cwg1567-B + using A::A; // #cwg1567-using-A + B(double); // #cwg1567-B-double }; A a{0}; @@ -384,22 +384,22 @@ B b3{B{1.0}}; // Good, copy/move ctors are not inherited B b4{a}; // since-cxx11-error@-1 {{no matching constructor for initialization of 'B'}} -// since-cxx11-note@#dr1567-A-int {{candidate inherited constructor not viable: no known conversion from 'A' to 'int' for 1st argument}} -// since-cxx11-note@#dr1567-using-A {{constructor from base class 'A' inherited here}} -// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'A' to 'const B' for 1st argument}} -// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'A' to 'B' for 1st argument}} -// since-cxx11-note@#dr1567-B-double {{candidate constructor not viable: no known conversion from 'A' to 'double' for 1st argument}} +// since-cxx11-note@#cwg1567-A-int {{candidate inherited constructor not viable: no known conversion from 'A' to 'int' for 1st argument}} +// since-cxx11-note@#cwg1567-using-A {{constructor from base class 'A' inherited here}} +// since-cxx11-note@#cwg1567-B {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'A' to 'const B' for 1st argument}} +// since-cxx11-note@#cwg1567-B {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'A' to 'B' for 1st argument}} +// since-cxx11-note@#cwg1567-B-double {{candidate constructor not viable: no known conversion from 'A' to 'double' for 1st argument}} B b5{A{0}}; // since-cxx11-error@-1 {{no matching constructor for initialization of 'B'}} -// since-cxx11-note@#dr1567-A-int {{candidate inherited constructor not viable: no known conversion from 'A' to 'int' for 1st argument}} -// since-cxx11-note@#dr1567-using-A {{constructor from base class 'A' inherited here}} -// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'A' to 'const B' for 1st argument}} -// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'A' to 'B' for 1st argument}} -// since-cxx11-note@#dr1567-B-double {{candidate constructor not viable: no known conversion from 'A' to 'double' for 1st argument}} +// since-cxx11-note@#cwg1567-A-int {{candidate inherited constructor not viable: no known conversion from 'A' to 'int' for 1st argument}} +// since-cxx11-note@#cwg1567-using-A {{constructor from base class 'A' inherited here}} +// since-cxx11-note@#cwg1567-B {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'A' to 'const B' for 1st argument}} +// since-cxx11-note@#cwg1567-B {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'A' to 'B' for 1st argument}} +// since-cxx11-note@#cwg1567-B-double {{candidate constructor not viable: no known conversion from 'A' to 'double' for 1st argument}} #endif } -namespace dr1573 { // dr1573: 3.9 +namespace cwg1573 { // cwg1573: 3.9 #if __cplusplus >= 201103L // ellipsis is inherited (p0136r1 supersedes this part). struct A { A(); A(int, char, ...); }; @@ -407,38 +407,38 @@ namespace dr1573 { // dr1573: 3.9 B b(1, 'x', 4.0, "hello"); // ok // inherited constructor is effectively constexpr if the user-written constructor would be - struct C { C(); constexpr C(int) {} }; // #dr1573-C + struct C { C(); constexpr C(int) {} }; // #cwg1573-C struct D : C { using C::C; }; constexpr D d = D(0); // ok - struct E : C { using C::C; A a; }; // #dr1573-E + struct E : C { using C::C; A a; }; // #cwg1573-E constexpr E e = E(0); // since-cxx11-error@-1 {{constexpr variable cannot have non-literal type 'const E'}} - // since-cxx11-note@#dr1573-E {{'E' is not literal because it has data member 'a' of non-literal type 'A'}} + // since-cxx11-note@#cwg1573-E {{'E' is not literal because it has data member 'a' of non-literal type 'A'}} // FIXME: This diagnostic is pretty bad; we should explain that the problem // is that F::c would be initialized by a non-constexpr constructor. - struct F : C { using C::C; C c; }; // #dr1573-F + struct F : C { using C::C; C c; }; // #cwg1573-F constexpr F f = F(0); // since-cxx11-error@-1 {{constexpr variable 'f' must be initialized by a constant expression}} // cxx11-20-note@-2 {{constructor inherited from base class 'C' cannot be used in a constant expression; derived class cannot be implicitly initialized}} // since-cxx23-note@-3 {{in implicit initialization for inherited constructor of 'F'}} - // since-cxx23-note@#dr1573-F {{non-constexpr constructor 'C' cannot be used in a constant expression}} - // cxx11-20-note@#dr1573-F {{declared here}} - // since-cxx23-note@#dr1573-C {{declared here}} + // since-cxx23-note@#cwg1573-F {{non-constexpr constructor 'C' cannot be used in a constant expression}} + // cxx11-20-note@#cwg1573-F {{declared here}} + // since-cxx23-note@#cwg1573-C {{declared here}} // inherited constructor is effectively deleted if the user-written constructor would be struct G { G(int); }; - struct H : G { using G::G; G g; }; // #dr1573-H + struct H : G { using G::G; G g; }; // #cwg1573-H H h(0); // since-cxx11-error@-1 {{constructor inherited by 'H' from base class 'G' is implicitly deleted}} - // since-cxx11-note@#dr1573-H {{constructor inherited by 'H' is implicitly deleted because field 'g' has no default constructor}} + // since-cxx11-note@#cwg1573-H {{constructor inherited by 'H' is implicitly deleted because field 'g' has no default constructor}} // deleted definition of constructor is inherited - struct I { I(int) = delete; }; // #dr1573-I + struct I { I(int) = delete; }; // #cwg1573-I struct J : I { using I::I; }; J j(0); // since-cxx11-error@-1 {{call to deleted constructor of 'J'}} - // since-cxx11-note@#dr1573-I {{'I' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1573-I {{'I' has been explicitly marked deleted here}} #endif } @@ -483,18 +483,18 @@ namespace std { } // std #endif -namespace dr1579 { // dr1579: 3.9 +namespace cwg1579 { // cwg1579: 3.9 #if __cplusplus >= 201103L template struct GenericMoveOnly { GenericMoveOnly(); - template GenericMoveOnly(const GenericMoveOnly &) = delete; // #dr1579-deleted-U - GenericMoveOnly(const int &) = delete; // #dr1579-deleted-int + template GenericMoveOnly(const GenericMoveOnly &) = delete; // #cwg1579-deleted-U + GenericMoveOnly(const int &) = delete; // #cwg1579-deleted-int template GenericMoveOnly(GenericMoveOnly &&); GenericMoveOnly(int &&); }; -GenericMoveOnly DR1579_Eligible(GenericMoveOnly CharMO) { +GenericMoveOnly CWG1579_Eligible(GenericMoveOnly CharMO) { int i; GenericMoveOnly GMO; @@ -510,7 +510,7 @@ GenericMoveOnly DR1579_Eligible(GenericMoveOnly CharMO) { GenericMoveOnly GlobalMO; -GenericMoveOnly DR1579_Ineligible(int &AnInt, +GenericMoveOnly CWG1579_Ineligible(int &AnInt, GenericMoveOnly &CharMO) { static GenericMoveOnly StaticMove; extern GenericMoveOnly ExternMove; @@ -518,63 +518,63 @@ GenericMoveOnly DR1579_Ineligible(int &AnInt, if (0) return AnInt; // since-cxx11-error@-1 {{conversion function from 'int' to 'GenericMoveOnly' invokes a deleted function}} - // since-cxx11-note@#dr1579-deleted-int {{'GenericMoveOnly' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1579-deleted-int {{'GenericMoveOnly' has been explicitly marked deleted here}} else if (0) return GlobalMO; // since-cxx11-error@-1 {{conversion function from 'GenericMoveOnly' to 'GenericMoveOnly' invokes a deleted function}} - // since-cxx11-note@#dr1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} else if (0) return StaticMove; // since-cxx11-error@-1 {{conversion function from 'GenericMoveOnly' to 'GenericMoveOnly' invokes a deleted function}} - // since-cxx11-note@#dr1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} else if (0) return ExternMove; // since-cxx11-error@-1 {{conversion function from 'GenericMoveOnly' to 'GenericMoveOnly' invokes a deleted function}} - // since-cxx11-note@#dr1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} else if (0) return AnInt; // since-cxx11-error@-1 {{conversion function from 'int' to 'GenericMoveOnly' invokes a deleted function}} - // since-cxx11-note@#dr1579-deleted-int {{'GenericMoveOnly' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1579-deleted-int {{'GenericMoveOnly' has been explicitly marked deleted here}} else return CharMO; // since-cxx11-error@-1 {{conversion function from 'GenericMoveOnly' to 'GenericMoveOnly' invokes a deleted function}} - // since-cxx11-note@#dr1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} } -auto DR1579_lambda_valid = [](GenericMoveOnly mo) -> +auto CWG1579_lambda_valid = [](GenericMoveOnly mo) -> GenericMoveOnly { return mo; }; -auto DR1579_lambda_invalid = []() -> GenericMoveOnly { +auto CWG1579_lambda_invalid = []() -> GenericMoveOnly { static GenericMoveOnly mo; return mo; // since-cxx11-error@-1 {{conversion function from 'GenericMoveOnly' to 'GenericMoveOnly' invokes a deleted function}} - // since-cxx11-note@#dr1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} + // since-cxx11-note@#cwg1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} }; #endif -} // end namespace dr1579 +} // end namespace cwg1579 -namespace dr1584 { +namespace cwg1584 { // cwg1584: 7 drafting 2015-05 #if __cplusplus >= 201103L // Deducing function types from cv-qualified types - template void f(const T *); // #dr1584-f + template void f(const T *); // #cwg1584-f template void g(T *, const T * = 0); template void h(T *) { T::error; } // since-cxx11-error@-1 {{type 'void ()' cannot be used prior to '::' because it has no members}} - // since-cxx11-note@#dr1584-h {{in instantiation of function template specialization 'dr1584::h' requested here}} + // since-cxx11-note@#cwg1584-h {{in instantiation of function template specialization 'cwg1584::h' requested here}} template void h(const T *); void i() { f(&i); // since-cxx11-error@-1 {{no matching function for call to 'f'}} - // since-cxx11-note@#dr1584-f {{candidate template ignored: could not match 'const T *' against 'void (*)()'}} + // since-cxx11-note@#cwg1584-f {{candidate template ignored: could not match 'const T *' against 'void (*)()'}} g(&i); - h(&i); // #dr1584-h + h(&i); // #cwg1584-h } #endif } -namespace dr1589 { // dr1589: 3.7 c++11 +namespace cwg1589 { // cwg1589: 3.7 c++11 #if __cplusplus >= 201103L // Ambiguous ranking of list-initialization sequences @@ -595,33 +595,33 @@ namespace dr1589 { // dr1589: 3.7 c++11 namespace with_error { void f0(long); - void f0(std::initializer_list); // #dr1589-f0-ilist - void f0(std::initializer_list, int = 0); // #dr1589-f0-ilist-int + void f0(std::initializer_list); // #cwg1589-f0-ilist + void f0(std::initializer_list, int = 0); // #cwg1589-f0-ilist-int void g0() { f0({1L}); } // since-cxx11-error@-1 {{call to 'f0' is ambiguous}} - // since-cxx11-note@#dr1589-f0-ilist {{candidate function}} - // since-cxx11-note@#dr1589-f0-ilist-int {{candidate function}} + // since-cxx11-note@#cwg1589-f0-ilist {{candidate function}} + // since-cxx11-note@#cwg1589-f0-ilist-int {{candidate function}} void f1(int); - void f1(std::initializer_list); // #dr1589-f1-ilist - void f1(std::initializer_list, int = 0); // #dr1589-f1-ilist-long + void f1(std::initializer_list); // #cwg1589-f1-ilist + void f1(std::initializer_list, int = 0); // #cwg1589-f1-ilist-long void g1() { f1({42}); } // since-cxx11-error@-1 {{call to 'f1' is ambiguous}} - // since-cxx11-note@#dr1589-f1-ilist {{candidate function}} - // since-cxx11-note@#dr1589-f1-ilist-long {{candidate function}} + // since-cxx11-note@#cwg1589-f1-ilist {{candidate function}} + // since-cxx11-note@#cwg1589-f1-ilist-long {{candidate function}} void f2(std::pair); - void f2(std::initializer_list); // #dr1589-f2-ilist - void f2(std::initializer_list, int = 0); // #dr1589-f2-ilist-int + void f2(std::initializer_list); // #cwg1589-f2-ilist + void f2(std::initializer_list, int = 0); // #cwg1589-f2-ilist-int void g2() { f2({"foo","bar"}); } // since-cxx11-error@-1 {{call to 'f2' is ambiguous}} - // since-cxx11-note@#dr1589-f2-ilist {{candidate function}} - // since-cxx11-note@#dr1589-f2-ilist-int {{candidate function}} + // since-cxx11-note@#cwg1589-f2-ilist {{candidate function}} + // since-cxx11-note@#cwg1589-f2-ilist-int {{candidate function}} } #endif -} // dr1589 +} // cwg1589 -namespace dr1591 { //dr1591. Deducing array bound and element type from initializer list +namespace cwg1591 { //cwg1591. Deducing array bound and element type from initializer list #if __cplusplus >= 201103L template int h(T const(&)[N]); int X = h({1,2,3}); // T deduced to int, N deduced to 3 @@ -630,10 +630,10 @@ namespace dr1591 { //dr1591. Deducing array bound and element type from initial int Y = j({42}); // T deduced to int, array bound not considered struct Aggr { int i; int j; }; - template int k(Aggr const(&)[N]); // #dr1591-k + template int k(Aggr const(&)[N]); // #cwg1591-k int Y0 = k({1,2,3}); // since-cxx11-error@-1 {{no matching function for call to 'k'}} - // since-cxx11-note@#dr1591-k {{candidate function [with N = 3] not viable: no known conversion from 'int' to 'const Aggr' for 1st argument}} + // since-cxx11-note@#cwg1591-k {{candidate function [with N = 3] not viable: no known conversion from 'int' to 'const Aggr' for 1st argument}} int Z = k({{1},{2},{3}}); // OK, N deduced to 3 template int m(int const(&)[M][N]); @@ -644,31 +644,31 @@ namespace dr1591 { //dr1591. Deducing array bound and element type from initial namespace check_multi_dim_arrays { - template int ***f(const T (&a)[N][M][O]); // #dr1591-f-3 - template int **f(const T (&a)[N][M]); // #dr1591-f-2 + template int ***f(const T (&a)[N][M][O]); // #cwg1591-f-3 + template int **f(const T (&a)[N][M]); // #cwg1591-f-2 - template int *f(const T (&a)[N]); // #dr1591-f-1 + template int *f(const T (&a)[N]); // #cwg1591-f-1 int ***p3 = f({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12} } }); int ***p33 = f({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12, 13} } }); // since-cxx11-error@-1 {{no matching function for call to 'f'}} - // since-cxx11-note@#dr1591-f-2 {{candidate template ignored: couldn't infer template argument 'T'}} - // since-cxx11-note@#dr1591-f-1 {{candidate template ignored: couldn't infer template argument 'T'}} - // since-cxx11-note@#dr1591-f-3 {{candidate template ignored: deduced conflicting values for parameter 'O' (2 vs. 3)}} + // since-cxx11-note@#cwg1591-f-2 {{candidate template ignored: couldn't infer template argument 'T'}} + // since-cxx11-note@#cwg1591-f-1 {{candidate template ignored: couldn't infer template argument 'T'}} + // since-cxx11-note@#cwg1591-f-3 {{candidate template ignored: deduced conflicting values for parameter 'O' (2 vs. 3)}} int **p2 = f({ {1,2,3}, {3, 4, 5} }); int **p22 = f({ {1,2}, {3, 4} }); int *p1 = f({1, 2, 3}); } namespace check_multi_dim_arrays_rref { - template int ***g(T (&&a)[N][M][O]); // #dr1591-g-3 - template int **g(T (&&a)[N][M]); // #dr1591-g-2 + template int ***g(T (&&a)[N][M][O]); // #cwg1591-g-3 + template int **g(T (&&a)[N][M]); // #cwg1591-g-2 - template int *g(T (&&a)[N]); // #dr1591-g-1 + template int *g(T (&&a)[N]); // #cwg1591-g-1 int ***p3 = g({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12} } }); int ***p33 = g({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12, 13} } }); // since-cxx11-error@-1 {{no matching function for call to 'g'}} - // since-cxx11-note@#dr1591-g-2 {{candidate template ignored: couldn't infer template argument 'T'}} - // since-cxx11-note@#dr1591-g-1 {{candidate template ignored: couldn't infer template argument 'T'}} - // since-cxx11-note@#dr1591-g-3 {{candidate template ignored: deduced conflicting values for parameter 'O' (2 vs. 3)}} + // since-cxx11-note@#cwg1591-g-2 {{candidate template ignored: couldn't infer template argument 'T'}} + // since-cxx11-note@#cwg1591-g-1 {{candidate template ignored: couldn't infer template argument 'T'}} + // since-cxx11-note@#cwg1591-g-3 {{candidate template ignored: deduced conflicting values for parameter 'O' (2 vs. 3)}} int **p2 = g({ {1,2,3}, {3, 4, 5} }); int **p22 = g({ {1,2}, {3, 4} }); int *p1 = g({1, 2, 3}); @@ -684,8 +684,8 @@ namespace dr1591 { //dr1591. Deducing array bound and element type from initial template int *i(T (&&)[N]); // #1 template char *i(std::initializer_list &&); // #2 - template int **i(T (&&)[N][M]); // #3 #dr1591-i-2 - template char **i(std::initializer_list (&&)[N]); // #4 #dr1591-i-1 + template int **i(T (&&)[N][M]); // #3 #cwg1591-i-2 + template char **i(std::initializer_list (&&)[N]); // #4 #cwg1591-i-1 template short *i(T (&&)[2]); // #5 @@ -697,11 +697,11 @@ namespace dr1591 { //dr1591. Deducing array bound and element type from initial void *pv1 = i({ {1, 2, 3}, {4, 5, 6} }); // ambiguous btw 3 & 4 // since-cxx11-error@-1 {{call to 'i' is ambiguous}} - // since-cxx11-note@#dr1591-i-2 {{candidate function [with T = int, N = 2, M = 3]}} - // since-cxx11-note@#dr1591-i-1 {{candidate function [with T = int, N = 2]}} + // since-cxx11-note@#cwg1591-i-2 {{candidate function [with T = int, N = 2, M = 3]}} + // since-cxx11-note@#cwg1591-i-1 {{candidate function [with T = int, N = 2]}} char **pcc = i({ {1}, {2, 3} }); // OK #4 short *ps = i(Arr{1, 2}); // OK #5 } #endif -} // dr1591 +} // cwg1591 diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp index f4d6c04fb8e0738d8d73a4f1a2f2ad13556bf897..6d7bb7619f8b8b5667c29597a747fa5b35c47f49 100644 --- a/clang/test/CXX/drs/dr16xx.cpp +++ b/clang/test/CXX/drs/dr16xx.cpp @@ -25,7 +25,7 @@ namespace std { } // std #endif -namespace dr1601 { // dr1601: 10 +namespace cwg1601 { // cwg1601: 10 enum E : char { e }; // cxx98-error@-1 {{enumeration types with a fixed underlying type are a C++11 extension}} void f(char); @@ -33,9 +33,9 @@ void f(int); void g() { f(e); } -} // namespace dr1601 +} // namespace cwg1601 -namespace dr1606 { // dr1606: 3.1 +namespace cwg1606 { // cwg1606: 3.1 #if __cplusplus >= 201103L std::size_t test() { int i = 1; @@ -44,16 +44,16 @@ namespace dr1606 { // dr1606: 3.1 return sizeof(f); } #endif -} // namespace dr1606 +} // namespace cwg1606 -namespace dr1611 { // dr1611: dup 1658 +namespace cwg1611 { // cwg1611: dup 1658 struct A { A(int); }; struct B : virtual A { virtual void f() = 0; }; struct C : B { C() : A(0) {} void f(); }; C c; } -namespace dr1631 { // dr1631: 3.7 +namespace cwg1631 { // cwg1631: 3.7 #if __cplusplus >= 201103L // Incorrect overload resolution for single-element initializer-list @@ -70,24 +70,24 @@ namespace dr1631 { // dr1631: 3.7 namespace with_error { void f(B, int); // TODO: expected- note {{candidate function}} - void f(int, A); // #dr1631-f - void f(int, A, int = 0); // #dr1631-f-int + void f(int, A); // #cwg1631-f + void f(int, A, int = 0); // #cwg1631-f-int void test() { f({0}, {{1}}); // since-cxx11-error@-1 {{call to 'f' is ambiguous}} - // since-cxx11-note@#dr1631-f {{candidate function}} - // since-cxx11-note@#dr1631-f-int {{candidate function}} + // since-cxx11-note@#cwg1631-f {{candidate function}} + // since-cxx11-note@#cwg1631-f-int {{candidate function}} } } #endif } -namespace dr1638 { // dr1638: 3.1 +namespace cwg1638 { // cwg1638: 3.1 #if __cplusplus >= 201103L template struct A { - enum class E; // #dr1638-E - enum class F : T; // #dr1638-F + enum class E; // #cwg1638-E + enum class F : T; // #cwg1638-F }; template<> enum class A::E; @@ -100,13 +100,13 @@ namespace dr1638 { // dr1638: 3.1 template<> enum class A::F; // since-cxx11-error@-1 {{enumeration redeclared with different underlying type 'int' (was 'short')}} - // since-cxx11-note@#dr1638-F {{previous declaration is here}} + // since-cxx11-note@#cwg1638-F {{previous declaration is here}} template<> enum class A::E : char; // since-cxx11-error@-1 {{enumeration redeclared with different underlying type 'char' (was 'int')}} - // since-cxx11-note@#dr1638-E {{previous declaration is here}} + // since-cxx11-note@#cwg1638-E {{previous declaration is here}} template<> enum class A::F : int; // since-cxx11-error@-1 {{enumeration redeclared with different underlying type 'int' (was 'char')}} - // since-cxx11-note@#dr1638-F {{previous declaration is here}} + // since-cxx11-note@#cwg1638-F {{previous declaration is here}} enum class A::E; // since-cxx11-error@-1 {{template specialization requires 'template<>'}} @@ -124,34 +124,34 @@ namespace dr1638 { // dr1638: 3.1 #endif } -namespace dr1645 { // dr1645: 3.9 +namespace cwg1645 { // cwg1645: 3.9 #if __cplusplus >= 201103L struct A { - constexpr A(int, float = 0); // #dr1645-int-float - explicit A(int, int = 0); // #dr1645-int-int - A(int, int, int = 0) = delete; // #dr1645-int-int-int + constexpr A(int, float = 0); // #cwg1645-int-float + explicit A(int, int = 0); // #cwg1645-int-int + A(int, int, int = 0) = delete; // #cwg1645-int-int-int }; struct B : A { - using A::A; // #dr1645-using + using A::A; // #cwg1645-using }; constexpr B a(0); // since-cxx11-error@-1 {{call to constructor of 'const B' is ambiguous}} - // since-cxx11-note@#dr1645-int-float {{candidate inherited constructor}} - // since-cxx11-note@#dr1645-using {{constructor from base class 'A' inherited here}} - // since-cxx11-note@#dr1645-int-int {{candidate inherited constructor}} - // since-cxx11-note@#dr1645-using {{constructor from base class 'A' inherited here}} + // since-cxx11-note@#cwg1645-int-float {{candidate inherited constructor}} + // since-cxx11-note@#cwg1645-using {{constructor from base class 'A' inherited here}} + // since-cxx11-note@#cwg1645-int-int {{candidate inherited constructor}} + // since-cxx11-note@#cwg1645-using {{constructor from base class 'A' inherited here}} constexpr B b(0, 0); // since-cxx11-error@-1 {{call to constructor of 'const B' is ambiguous}} - // since-cxx11-note@#dr1645-int-int {{candidate inherited constructor}} - // since-cxx11-note@#dr1645-using {{constructor from base class 'A' inherited here}} - // since-cxx11-note@#dr1645-int-int-int {{candidate inherited constructor has been explicitly deleted}} - // since-cxx11-note@#dr1645-using {{constructor from base class 'A' inherited here}} + // since-cxx11-note@#cwg1645-int-int {{candidate inherited constructor}} + // since-cxx11-note@#cwg1645-using {{constructor from base class 'A' inherited here}} + // since-cxx11-note@#cwg1645-int-int-int {{candidate inherited constructor has been explicitly deleted}} + // since-cxx11-note@#cwg1645-using {{constructor from base class 'A' inherited here}} #endif } -namespace dr1652 { // dr1652: 3.6 +namespace cwg1652 { // cwg1652: 3.6 int a, b; int arr[&a + 1 == &b ? 1 : 2]; // expected-error@-1 {{variable length arrays in C++ are a Clang extension}} @@ -159,7 +159,7 @@ namespace dr1652 { // dr1652: 3.6 // expected-error@-3 {{variable length array declaration not allowed at file scope}} } -namespace dr1653 { // dr1653: 4 c++17 +namespace cwg1653 { // cwg1653: 4 c++17 void f(bool b) { ++b; // cxx98-14-warning@-1 {{incrementing expression of type bool is deprecated and incompatible with C++17}} @@ -176,10 +176,10 @@ namespace dr1653 { // dr1653: 4 c++17 } } -namespace dr1658 { // dr1658: 5 +namespace cwg1658 { // cwg1658: 5 namespace DefCtor { - class A { A(); }; // #dr1658-A1 - class B { ~B(); }; // #dr1658-B1 + class A { A(); }; // #cwg1658-A1 + class B { ~B(); }; // #cwg1658-B1 // The stars align! An abstract class does not construct its virtual bases. struct C : virtual A { C(); virtual void foo() = 0; }; @@ -190,76 +190,76 @@ namespace dr1658 { // dr1658: 5 // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} // In all other cases, we are not so lucky. - struct E : A { E(); virtual void foo() = 0; }; // #dr1658-E1 - E::E() = default; // #dr1658-E1-ctor + struct E : A { E(); virtual void foo() = 0; }; // #cwg1658-E1 + E::E() = default; // #cwg1658-E1-ctor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} // cxx98-error@-2 {{base class 'A' has private default constructor}} - // cxx98-note@-3 {{in defaulted default constructor for 'dr1658::DefCtor::E' first required here}} - // cxx98-note@#dr1658-A1 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-E1-ctor {{defaulting this default constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-E1 {{default constructor of 'E' is implicitly deleted because base class 'A' has an inaccessible default constructor}} - struct F : virtual A { F(); }; // #dr1658-F1 - F::F() = default; // #dr1658-F1-ctor + // cxx98-note@-3 {{in defaulted default constructor for 'cwg1658::DefCtor::E' first required here}} + // cxx98-note@#cwg1658-A1 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-E1-ctor {{defaulting this default constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-E1 {{default constructor of 'E' is implicitly deleted because base class 'A' has an inaccessible default constructor}} + struct F : virtual A { F(); }; // #cwg1658-F1 + F::F() = default; // #cwg1658-F1-ctor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} // cxx98-error@-2 {{inherited virtual base class 'A' has private default constructor}} - // cxx98-note@-3 {{in defaulted default constructor for 'dr1658::DefCtor::F' first required here}} - // cxx98-note@#dr1658-A1 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-F1-ctor {{defaulting this default constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-F1 {{default constructor of 'F' is implicitly deleted because base class 'A' has an inaccessible default constructor}} + // cxx98-note@-3 {{in defaulted default constructor for 'cwg1658::DefCtor::F' first required here}} + // cxx98-note@#cwg1658-A1 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-F1-ctor {{defaulting this default constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-F1 {{default constructor of 'F' is implicitly deleted because base class 'A' has an inaccessible default constructor}} - struct G : B { G(); virtual void foo() = 0; }; // #dr1658-G1 - G::G() = default; // #dr1658-G1-ctor + struct G : B { G(); virtual void foo() = 0; }; // #cwg1658-G1 + G::G() = default; // #cwg1658-G1-ctor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} - // cxx98-error@#dr1658-G1 {{base class 'B' has private destructor}} - // cxx98-note@#dr1658-G1-ctor {{in defaulted default constructor for 'dr1658::DefCtor::G' first required here}} - // cxx98-note@#dr1658-B1 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-G1-ctor {{defaulting this default constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-G1 {{default constructor of 'G' is implicitly deleted because base class 'B' has an inaccessible destructor}} - struct H : virtual B { H(); }; // #dr1658-H1 - H::H() = default; // #dr1658-H1-ctor + // cxx98-error@#cwg1658-G1 {{base class 'B' has private destructor}} + // cxx98-note@#cwg1658-G1-ctor {{in defaulted default constructor for 'cwg1658::DefCtor::G' first required here}} + // cxx98-note@#cwg1658-B1 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-G1-ctor {{defaulting this default constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-G1 {{default constructor of 'G' is implicitly deleted because base class 'B' has an inaccessible destructor}} + struct H : virtual B { H(); }; // #cwg1658-H1 + H::H() = default; // #cwg1658-H1-ctor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} - // cxx98-error@#dr1658-H1 {{base class 'B' has private destructor}} - // cxx98-note@#dr1658-H1-ctor {{in defaulted default constructor for 'dr1658::DefCtor::H' first required here}} - // cxx98-note@#dr1658-B1 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-H1-ctor {{defaulting this default constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-H1 {{default constructor of 'H' is implicitly deleted because base class 'B' has an inaccessible destructor}} + // cxx98-error@#cwg1658-H1 {{base class 'B' has private destructor}} + // cxx98-note@#cwg1658-H1-ctor {{in defaulted default constructor for 'cwg1658::DefCtor::H' first required here}} + // cxx98-note@#cwg1658-B1 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-H1-ctor {{defaulting this default constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-H1 {{default constructor of 'H' is implicitly deleted because base class 'B' has an inaccessible destructor}} } namespace Dtor { - class B { ~B(); }; // #dr1658-B2 + class B { ~B(); }; // #cwg1658-B2 struct D : virtual B { ~D(); virtual void foo() = 0; }; D::~D() = default; // ok, not deleted // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} - struct G : B { ~G(); virtual void foo() = 0; }; // #dr1658-G2 - G::~G() = default; // #dr1658-G2-dtor + struct G : B { ~G(); virtual void foo() = 0; }; // #cwg1658-G2 + G::~G() = default; // #cwg1658-G2-dtor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} - // cxx98-error@#dr1658-G2 {{base class 'B' has private destructor}} - // cxx98-note@#dr1658-G2-dtor {{in defaulted destructor for 'dr1658::Dtor::G' first required here}} - // cxx98-note@#dr1658-B2 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-G2-dtor {{defaulting this destructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-G2 {{destructor of 'G' is implicitly deleted because base class 'B' has an inaccessible destructor}} - struct H : virtual B { ~H(); }; // #dr1658-H2 - H::~H() = default; // #dr1658-H2-dtor + // cxx98-error@#cwg1658-G2 {{base class 'B' has private destructor}} + // cxx98-note@#cwg1658-G2-dtor {{in defaulted destructor for 'cwg1658::Dtor::G' first required here}} + // cxx98-note@#cwg1658-B2 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-G2-dtor {{defaulting this destructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-G2 {{destructor of 'G' is implicitly deleted because base class 'B' has an inaccessible destructor}} + struct H : virtual B { ~H(); }; // #cwg1658-H2 + H::~H() = default; // #cwg1658-H2-dtor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} - // cxx98-error@#dr1658-H2 {{base class 'B' has private destructor}} - // cxx98-note@#dr1658-H2-dtor {{in defaulted destructor for 'dr1658::Dtor::H' first required here}} - // cxx98-note@#dr1658-B2 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-H2-dtor {{defaulting this destructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-H2 {{destructor of 'H' is implicitly deleted because base class 'B' has an inaccessible destructor}} + // cxx98-error@#cwg1658-H2 {{base class 'B' has private destructor}} + // cxx98-note@#cwg1658-H2-dtor {{in defaulted destructor for 'cwg1658::Dtor::H' first required here}} + // cxx98-note@#cwg1658-B2 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-H2-dtor {{defaulting this destructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-H2 {{destructor of 'H' is implicitly deleted because base class 'B' has an inaccessible destructor}} } namespace MemInit { - struct A { A(int); }; // #dr1658-A3 + struct A { A(int); }; // #cwg1658-A3 struct B : virtual A { B() {} virtual void f() = 0; }; struct C : virtual A { C() {} - // expected-error@-1 {{constructor for 'dr1658::MemInit::C' must explicitly initialize the base class 'A' which does not have a default constructor}} - // expected-note@#dr1658-A3 {{'dr1658::MemInit::A' declared here}} + // expected-error@-1 {{constructor for 'cwg1658::MemInit::C' must explicitly initialize the base class 'A' which does not have a default constructor}} + // expected-note@#cwg1658-A3 {{'cwg1658::MemInit::A' declared here}} }; } @@ -277,7 +277,7 @@ namespace dr1658 { // dr1658: 5 } namespace CopyCtor { - class A { A(const A&); A(A&&); }; // #dr1658-A5 + class A { A(const A&); A(A&&); }; // #cwg1658-A5 // cxx98-error@-1 {{rvalue references are a C++11 extension}} struct C : virtual A { C(const C&); C(C&&); virtual void foo() = 0; }; @@ -288,46 +288,46 @@ namespace dr1658 { // dr1658: 5 // cxx98-error@-1 {{rvalue references are a C++11 extension}} // cxx98-error@-2 {{defaulted function definitions are a C++11 extension}} - struct E : A { E(const E&); E(E&&); virtual void foo() = 0; }; // #dr1658-E5 + struct E : A { E(const E&); E(E&&); virtual void foo() = 0; }; // #cwg1658-E5 // cxx98-error@-1 {{rvalue references are a C++11 extension}} - E::E(const E&) = default; // #dr1658-E5-copy-ctor + E::E(const E&) = default; // #cwg1658-E5-copy-ctor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} // cxx98-error@-2 {{base class 'A' has private copy constructor}} - // cxx98-note@-3 {{in defaulted copy constructor for 'dr1658::CopyCtor::E' first required here}} - // cxx98-note@#dr1658-A5 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-E5-copy-ctor {{defaulting this copy constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-E5 {{copy constructor of 'E' is implicitly deleted because base class 'A' has an inaccessible copy constructor}} - E::E(E&&) = default; // #dr1658-E5-move-ctor + // cxx98-note@-3 {{in defaulted copy constructor for 'cwg1658::CopyCtor::E' first required here}} + // cxx98-note@#cwg1658-A5 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-E5-copy-ctor {{defaulting this copy constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-E5 {{copy constructor of 'E' is implicitly deleted because base class 'A' has an inaccessible copy constructor}} + E::E(E&&) = default; // #cwg1658-E5-move-ctor // cxx98-error@-1 {{rvalue references are a C++11 extension}} // cxx98-error@-2 {{defaulted function definitions are a C++11 extension}} // cxx98-error@-3 {{base class 'A' has private move constructor}} - // cxx98-note@-4 {{in defaulted move constructor for 'dr1658::CopyCtor::E' first required here}} - // cxx98-note@#dr1658-A5 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-E5-move-ctor {{defaulting this move constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-E5 {{move constructor of 'E' is implicitly deleted because base class 'A' has an inaccessible move constructor}} - struct F : virtual A { F(const F&); F(F&&); }; // #dr1658-F5 + // cxx98-note@-4 {{in defaulted move constructor for 'cwg1658::CopyCtor::E' first required here}} + // cxx98-note@#cwg1658-A5 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-E5-move-ctor {{defaulting this move constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-E5 {{move constructor of 'E' is implicitly deleted because base class 'A' has an inaccessible move constructor}} + struct F : virtual A { F(const F&); F(F&&); }; // #cwg1658-F5 // cxx98-error@-1 {{rvalue references are a C++11 extension}} - F::F(const F&) = default; // #dr1658-F5-copy-ctor + F::F(const F&) = default; // #cwg1658-F5-copy-ctor // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} // cxx98-error@-2 {{inherited virtual base class 'A' has private copy constructor}} - // cxx98-note@-3 {{in defaulted copy constructor for 'dr1658::CopyCtor::F' first required here}} - // cxx98-note@#dr1658-A5 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-F5-copy-ctor {{defaulting this copy constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-F5 {{copy constructor of 'F' is implicitly deleted because base class 'A' has an inaccessible copy constructor}} - F::F(F&&) = default; // #dr1658-F5-move-ctor + // cxx98-note@-3 {{in defaulted copy constructor for 'cwg1658::CopyCtor::F' first required here}} + // cxx98-note@#cwg1658-A5 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-F5-copy-ctor {{defaulting this copy constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-F5 {{copy constructor of 'F' is implicitly deleted because base class 'A' has an inaccessible copy constructor}} + F::F(F&&) = default; // #cwg1658-F5-move-ctor // cxx98-error@-1 {{rvalue references are a C++11 extension}} // cxx98-error@-2 {{defaulted function definitions are a C++11 extension}} // cxx98-error@-3 {{inherited virtual base class 'A' has private move constructor}} - // cxx98-note@-4 {{in defaulted move constructor for 'dr1658::CopyCtor::F' first required here}} - // cxx98-note@#dr1658-A5 {{implicitly declared private here}} - // since-cxx11-error@#dr1658-F5-move-ctor {{defaulting this move constructor would delete it after its first declaration}} - // since-cxx11-note@#dr1658-F5 {{move constructor of 'F' is implicitly deleted because base class 'A' has an inaccessible move constructor}} + // cxx98-note@-4 {{in defaulted move constructor for 'cwg1658::CopyCtor::F' first required here}} + // cxx98-note@#cwg1658-A5 {{implicitly declared private here}} + // since-cxx11-error@#cwg1658-F5-move-ctor {{defaulting this move constructor would delete it after its first declaration}} + // since-cxx11-note@#cwg1658-F5 {{move constructor of 'F' is implicitly deleted because base class 'A' has an inaccessible move constructor}} } - // assignment case is superseded by dr2180 + // assignment case is superseded by cwg2180 } -namespace dr1672 { // dr1672: 7 +namespace cwg1672 { // cwg1672: 7 struct Empty {}; struct A : Empty {}; struct B { Empty e; }; @@ -352,9 +352,9 @@ namespace dr1672 { // dr1672: 7 static_assert(!__is_standard_layout(Y), ""); } -namespace dr1684 { // dr1684: 3.6 +namespace cwg1684 { // cwg1684: 3.6 #if __cplusplus >= 201103L - struct NonLiteral { // #dr1684-struct + struct NonLiteral { // #cwg1684-struct NonLiteral(); constexpr int f() { return 0; } // cxx11-warning@-1 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const' to avoid a change in behavior}} @@ -362,34 +362,34 @@ namespace dr1684 { // dr1684: 3.6 constexpr int f(NonLiteral &) { return 0; } constexpr int f(NonLiteral) { return 0; } // cxx11-20-error@-1 {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} - // cxx11-20-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + // cxx11-20-note@#cwg1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} #endif } -namespace dr1687 { // dr1687: 7 +namespace cwg1687 { // cwg1687: 7 template struct To { - operator T(); // #dr1687-op-T + operator T(); // #cwg1687-op-T }; int *a = To() + 100.0; // expected-error@-1 {{invalid operands to binary expression ('To' and 'double')}} - // expected-note@#dr1687-op-T {{first operand was implicitly converted to type 'int *'}} - // since-cxx20-note@#dr1687-op-T {{second operand was implicitly converted to type 'dr1687::E2'}} + // expected-note@#cwg1687-op-T {{first operand was implicitly converted to type 'int *'}} + // since-cxx20-note@#cwg1687-op-T {{second operand was implicitly converted to type 'cwg1687::E2'}} int *b = To() + To(); // expected-error@-1 {{invalid operands to binary expression ('To' and 'To')}} - // expected-note@#dr1687-op-T {{first operand was implicitly converted to type 'int *'}} - // expected-note@#dr1687-op-T {{second operand was implicitly converted to type 'double'}} + // expected-note@#cwg1687-op-T {{first operand was implicitly converted to type 'int *'}} + // expected-note@#cwg1687-op-T {{second operand was implicitly converted to type 'double'}} #if __cplusplus >= 202002L enum E1 {}; enum E2 {}; auto c = To() <=> To(); // since-cxx20-error@-1 {{invalid operands to binary expression ('To' and 'To')}} - // since-cxx20-note@#dr1687-op-T {{operand was implicitly converted to type 'dr1687::E}} + // since-cxx20-note@#cwg1687-op-T {{operand was implicitly converted to type 'cwg1687::E}} #endif } -namespace dr1690 { // dr1690: 9 +namespace cwg1690 { // cwg1690: 9 // See also the various tests in "CXX/basic/basic.lookup/basic.lookup.argdep". #if __cplusplus >= 201103L namespace N { @@ -404,7 +404,7 @@ namespace dr1690 { // dr1690: 9 #endif } -namespace dr1691 { // dr1691: 9 +namespace cwg1691 { // cwg1691: 9 #if __cplusplus >= 201103L namespace N { namespace M { @@ -412,19 +412,19 @@ namespace dr1691 { // dr1691: 9 void f(E); } enum M::E : int {}; - void g(M::E); // #dr1691-g + void g(M::E); // #cwg1691-g } void test() { N::M::E e; f(e); // ok g(e); // since-cxx11-error@-1 {{use of undeclared identifier 'g'; did you mean 'N::g'?}} - // since-cxx11-note@#dr1691-g {{'N::g' declared here}} + // since-cxx11-note@#cwg1691-g {{'N::g' declared here}} } #endif } -namespace dr1692 { // dr1692: 9 +namespace cwg1692 { // cwg1692: 9 namespace N { struct A { struct B { @@ -439,7 +439,7 @@ namespace dr1692 { // dr1692: 9 } } -namespace dr1696 { // dr1696: 7 +namespace cwg1696 { // cwg1696: 7 namespace std_examples { #if __cplusplus >= 201402L extern struct A a; @@ -456,66 +456,66 @@ namespace dr1696 { // dr1696: 7 struct A { A(); ~A(); }; #if __cplusplus >= 201103L struct B { - A &&a; // #dr1696-a + A &&a; // #cwg1696-a B() : a{} {} // since-cxx11-error@-1 {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // since-cxx11-note@#dr1696-a {{reference member declared here}} + // since-cxx11-note@#cwg1696-a {{reference member declared here}} } b; #endif struct C { C(); - const A &a; // #dr1696-C-a + const A &a; // #cwg1696-C-a }; C::C() : a(A()) {} // expected-error@-1 {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // expected-note@#dr1696-C-a {{reference member declared here}} + // expected-note@#cwg1696-C-a {{reference member declared here}} #if __cplusplus >= 201103L - // This is OK in C++14 onwards, per DR1815, though we don't support that yet: + // This is OK in C++14 onwards, per CWG1815, though we don't support that yet: // D1 d1 = {}; // is equivalent to // D1 d1 = {A()}; // ... which lifetime-extends the A temporary. struct D1 { // cxx11-error@-1 {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // cxx11-note@#dr1696-d1 {{in implicit default constructor for 'dr1696::D1' first required here}} - // cxx11-note@#dr1696-D1-a {{initializing field 'a' with default member initializer}} - const A &a = A(); // #dr1696-D1-a + // cxx11-note@#cwg1696-d1 {{in implicit default constructor for 'cwg1696::D1' first required here}} + // cxx11-note@#cwg1696-D1-a {{initializing field 'a' with default member initializer}} + const A &a = A(); // #cwg1696-D1-a }; - D1 d1 = {}; // #dr1696-d1 + D1 d1 = {}; // #cwg1696-d1 // since-cxx14-warning@-1 {{lifetime extension of temporary created by aggregate initialization using a default member initializer is not yet supported; lifetime of temporary will end at the end of the full-expression}} - // since-cxx14-note@#dr1696-D1-a {{initializing field 'a' with default member initializer}} + // since-cxx14-note@#cwg1696-D1-a {{initializing field 'a' with default member initializer}} struct D2 { - const A &a = A(); // #dr1696-D2-a + const A &a = A(); // #cwg1696-D2-a D2() {} // since-cxx11-error@-1 {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // since-cxx11-note@#dr1696-D2-a {{initializing field 'a' with default member initializer}} + // since-cxx11-note@#cwg1696-D2-a {{initializing field 'a' with default member initializer}} }; struct D3 { // since-cxx11-error@-1 {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // since-cxx11-note@#dr1696-d3 {{in implicit default constructor for 'dr1696::D3' first required here}} - // since-cxx11-note@#dr1696-D3-a {{initializing field 'a' with default member initializer}} - const A &a = A(); // #dr1696-D3-a + // since-cxx11-note@#cwg1696-d3 {{in implicit default constructor for 'cwg1696::D3' first required here}} + // since-cxx11-note@#cwg1696-D3-a {{initializing field 'a' with default member initializer}} + const A &a = A(); // #cwg1696-D3-a }; - D3 d3; // #dr1696-d3 + D3 d3; // #cwg1696-d3 struct haslist1 { - std::initializer_list il; // #dr1696-il-1 + std::initializer_list il; // #cwg1696-il-1 haslist1(int i) : il{i, 2, 3} {} // since-cxx11-error@-1 {{backing array for 'std::initializer_list' member 'il' is a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // since-cxx11-note@#dr1696-il-1 {{'std::initializer_list' member declared here}} + // since-cxx11-note@#cwg1696-il-1 {{'std::initializer_list' member declared here}} }; struct haslist2 { - std::initializer_list il; // #dr1696-il-2 + std::initializer_list il; // #cwg1696-il-2 haslist2(); }; haslist2::haslist2() : il{1, 2} {} // since-cxx11-error@-1 {{backing array for 'std::initializer_list' member 'il' is a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // since-cxx11-note@#dr1696-il-2 {{'std::initializer_list' member declared here}} + // since-cxx11-note@#cwg1696-il-2 {{'std::initializer_list' member declared here}} struct haslist3 { std::initializer_list il = {1, 2, 3}; @@ -523,17 +523,17 @@ namespace dr1696 { // dr1696: 7 struct haslist4 { // since-cxx11-error@-1 {{backing array for 'std::initializer_list' member 'il' is a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // since-cxx11-note@#dr1696-hl4 {{in implicit default constructor for 'dr1696::haslist4' first required here}} - // since-cxx11-note@#dr1696-il-4 {{initializing field 'il' with default member initializer}} - std::initializer_list il = {1, 2, 3}; // #dr1696-il-4 + // since-cxx11-note@#cwg1696-hl4 {{in implicit default constructor for 'cwg1696::haslist4' first required here}} + // since-cxx11-note@#cwg1696-il-4 {{initializing field 'il' with default member initializer}} + std::initializer_list il = {1, 2, 3}; // #cwg1696-il-4 }; - haslist4 hl4; // #dr1696-hl4 + haslist4 hl4; // #cwg1696-hl4 struct haslist5 { - std::initializer_list il = {1, 2, 3}; // #dr1696-il-5 + std::initializer_list il = {1, 2, 3}; // #cwg1696-il-5 haslist5() {} // since-cxx11-error@-1 {{backing array for 'std::initializer_list' member 'il' is a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // since-cxx11-note@#dr1696-il-5 {{nitializing field 'il' with default member initializer}} + // since-cxx11-note@#cwg1696-il-5 {{nitializing field 'il' with default member initializer}} }; #endif } diff --git a/clang/test/CXX/drs/dr17xx.cpp b/clang/test/CXX/drs/dr17xx.cpp index d3cb5e58f06b3218829375b92032582ebd653f3f..fb53a56923b104a6ba1ff19429f0930989ba1598 100644 --- a/clang/test/CXX/drs/dr17xx.cpp +++ b/clang/test/CXX/drs/dr17xx.cpp @@ -6,7 +6,7 @@ // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -namespace dr1710 { // dr1710: no +namespace cwg1710 { // cwg1710: no // FIXME: all of the following is well-formed template struct D1 : T::template B::template C {}; template struct D2 : T::B::template C {}; @@ -16,9 +16,9 @@ template struct D3 : T::template B::C {}; template struct D4 : T::B::C {}; // expected-error@-1 {{use 'template' keyword to treat 'B' as a dependent template name}} // expected-error@-2 {{use 'template' keyword to treat 'C' as a dependent template name}} -} // namespace dr1710 +} // namespace cwg1710 -namespace dr1715 { // dr1715: 3.9 +namespace cwg1715 { // cwg1715: 3.9 #if __cplusplus >= 201103L struct B { template B(T, typename T::Q); @@ -32,21 +32,21 @@ namespace dr1715 { // dr1715: 3.9 struct D : B { using B::B; }; - struct E : B { // #dr1715-E - template E(T t, typename T::Q q) : B(t, q) {} // #dr1715-E-ctor + struct E : B { // #cwg1715-E + template E(T t, typename T::Q q) : B(t, q) {} // #cwg1715-E-ctor }; B b(S(), 1); D d(S(), 2); E e(S(), 3); // since-cxx11-error@-1 {{no matching constructor for initialization of 'E'}} - // since-cxx11-note@#dr1715-E-ctor {{candidate template ignored: substitution failure [with T = S]: 'Q' is a private member of 'dr1715::S'}} - // since-cxx11-note@#dr1715-E {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} - // since-cxx11-note@#dr1715-E {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} + // since-cxx11-note@#cwg1715-E-ctor {{candidate template ignored: substitution failure [with T = S]: 'Q' is a private member of 'cwg1715::S'}} + // since-cxx11-note@#cwg1715-E {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} + // since-cxx11-note@#cwg1715-E {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} #endif } -namespace dr1719 { // dr1719: 19 +namespace cwg1719 { // cwg1719: 19 #if __cplusplus >= 201103L struct CStruct { int one; @@ -72,9 +72,9 @@ static_assert(__is_layout_compatible(const int, volatile int), ""); static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers), ""); static_assert(__is_layout_compatible(int[], const volatile int[]), ""); #endif -} // namespace dr1719 +} // namespace cwg1719 -namespace dr1722 { // dr1722: 9 +namespace cwg1722 { // cwg1722: 9 #if __cplusplus >= 201103L void f() { const auto lambda = [](int x) { return x + 1; }; @@ -84,9 +84,9 @@ void f() { "Lambda-to-function-pointer conversion is expected to be noexcept"); } #endif -} // namespace dr1722 +} // namespace cwg1722 -namespace dr1734 { // dr1734: no +namespace cwg1734 { // cwg1734: no #if __cplusplus >= 201103L struct A { A(const A&) = delete; @@ -98,7 +98,7 @@ static_assert(__is_trivially_copyable(A), ""); #endif } -namespace dr1736 { // dr1736: 3.9 +namespace cwg1736 { // cwg1736: 3.9 #if __cplusplus >= 201103L struct S { template S(T t) { @@ -107,17 +107,17 @@ struct S { }; typename T::type value; // since-cxx11-error@-1 {{type 'int' cannot be used prior to '::' because it has no members}} - // since-cxx11-note@#dr1736-l {{in instantiation of function template specialization 'dr1736::S::S' requested here}} - // since-cxx11-note@#dr1736-s {{in instantiation of function template specialization 'dr1736::S::S' requested here}} - L l(value); // #dr1736-l + // since-cxx11-note@#cwg1736-l {{in instantiation of function template specialization 'cwg1736::S::S' requested here}} + // since-cxx11-note@#cwg1736-s {{in instantiation of function template specialization 'cwg1736::S::S' requested here}} + L l(value); // #cwg1736-l } }; struct Q { typedef int type; } q; -S s(q); // #dr1736-s +S s(q); // #cwg1736-s #endif } -namespace dr1738 { // dr1738: sup P0136R1 +namespace cwg1738 { // cwg1738: sup P0136R1 #if __cplusplus >= 201103L struct A { template @@ -134,9 +134,9 @@ template B::B(int, double); #endif } -// dr1748 is in dr1748.cpp +// cwg1748 is in cwg1748.cpp -namespace dr1753 { // dr1753: 11 +namespace cwg1753 { // cwg1753: 11 typedef int T; struct A { typedef int T; }; namespace B { typedef int T; } @@ -145,9 +145,9 @@ namespace dr1753 { // dr1753: 11 n.~T(); n.T::~T(); - n.dr1753::~T(); - // expected-error@-1 {{'dr1753' does not refer to a type name in pseudo-destructor expression; expected the name of type 'T' (aka 'int')}} - n.dr1753::T::~T(); + n.cwg1753::~T(); + // expected-error@-1 {{'cwg1753' does not refer to a type name in pseudo-destructor expression; expected the name of type 'T' (aka 'int')}} + n.cwg1753::T::~T(); n.A::~T(); // expected-error@-1 {{the type of object expression ('T' (aka 'int')) does not match the type being destroyed ('A') in pseudo-destructor expression}} @@ -167,7 +167,7 @@ namespace dr1753 { // dr1753: 11 } } -namespace dr1756 { // dr1756: 3.7 +namespace cwg1756 { // cwg1756: 3.7 #if __cplusplus >= 201103L // Direct-list-initialization of a non-class object @@ -178,7 +178,7 @@ namespace dr1756 { // dr1756: 3.7 #endif } -namespace dr1758 { // dr1758: 3.7 +namespace cwg1758 { // cwg1758: 3.7 #if __cplusplus >= 201103L // Explicit conversion in copy/move list initialization @@ -197,7 +197,7 @@ namespace dr1758 { // dr1758: 3.7 #endif } -namespace dr1762 { // dr1762: 14 +namespace cwg1762 { // cwg1762: 14 #if __cplusplus >= 201103L float operator ""_E(const char *); float operator ""E(const char *); @@ -206,9 +206,9 @@ namespace dr1762 { // dr1762: 14 #endif } -// dr1772 is in dr177x.cpp +// cwg1772 is in cwg177x.cpp -namespace dr1778 { // dr1778: 9 +namespace cwg1778 { // cwg1778: 9 // Superseded by P1286R2. #if __cplusplus >= 201103L struct A { A() noexcept(true) = default; }; @@ -223,9 +223,9 @@ namespace dr1778 { // dr1778: 9 #endif } -// dr1779 is in dr177x.cpp +// cwg1779 is in cwg177x.cpp -namespace dr1794 { // dr1794: yes +namespace cwg1794 { // cwg1794: yes // NB: dup 1710 #if __cplusplus >= 201103L template