diff --git a/.github/workflows/issue-release-workflow.yml b/.github/workflows/issue-release-workflow.yml index eb88ec6e43c57409b6656c9b3e21bdc7cf76fede..5027d4f3ea6f10a6b56341386e9b44070e206436 100644 --- a/.github/workflows/issue-release-workflow.yml +++ b/.github/workflows/issue-release-workflow.yml @@ -53,7 +53,7 @@ jobs: - name: Setup Environment run: | - pip install -r ./llvm/utils/git/requirements.txt + pip install --require-hashes -r ./llvm/utils/git/requirements.txt ./llvm/utils/git/github-automation.py --token ${{ github.token }} setup-llvmbot-git - name: Backport Commits diff --git a/.github/workflows/issue-subscriber.yml b/.github/workflows/issue-subscriber.yml index ef6cd0674e8085c19d56b27f428f788066a05b59..ef4fdf44181938dea5d002cd0a63c64120eb7270 100644 --- a/.github/workflows/issue-subscriber.yml +++ b/.github/workflows/issue-subscriber.yml @@ -22,7 +22,7 @@ jobs: - name: Setup Automation Script working-directory: ./llvm/utils/git/ run: | - pip install -r requirements.txt + pip install --require-hashes -r requirements.txt - name: Update watchers working-directory: ./llvm/utils/git/ diff --git a/.github/workflows/llvm-bugs.yml b/.github/workflows/llvm-bugs.yml index f592dd6ccd90331cf1338b8ce803faefe56da874..c392078fa45251355e0226e42eefdbfef01ee814 100644 --- a/.github/workflows/llvm-bugs.yml +++ b/.github/workflows/llvm-bugs.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'llvm/llvm-project' steps: - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 check-latest: true diff --git a/.github/workflows/merged-prs.yml b/.github/workflows/merged-prs.yml index 37fc6c67f000baa4da677313bbe7e316ccaaa14c..e29afd4097f9fbe5adf22ae77d5d0cf9f3fa3186 100644 --- a/.github/workflows/merged-prs.yml +++ b/.github/workflows/merged-prs.yml @@ -29,7 +29,7 @@ jobs: - name: Setup Automation Script working-directory: ./llvm/utils/git/ run: | - pip install -r requirements.txt + pip install --require-hashes -r requirements.txt - name: Add Buildbot information comment working-directory: ./llvm/utils/git/ diff --git a/.github/workflows/new-prs.yml b/.github/workflows/new-prs.yml index a60f82ce35d1f317ae474a74fec036294326da0e..88175d6f8d64d4bbbb034ae4985eefa8427e2550 100644 --- a/.github/workflows/new-prs.yml +++ b/.github/workflows/new-prs.yml @@ -43,7 +43,7 @@ jobs: - name: Setup Automation Script working-directory: ./llvm/utils/git/ run: | - pip install -r requirements.txt + pip install --require-hashes -r requirements.txt - name: Greet Author working-directory: ./llvm/utils/git/ diff --git a/.github/workflows/pr-request-release-note.yml b/.github/workflows/pr-request-release-note.yml index 0fcb95f1fe29497ab1cac063061745d88ade7dcd..5e48ce7aee2e2b32d1f2fc3a086358454e63c056 100644 --- a/.github/workflows/pr-request-release-note.yml +++ b/.github/workflows/pr-request-release-note.yml @@ -29,7 +29,7 @@ jobs: - name: Install Dependencies run: | - pip install -r llvm/utils/git/requirements.txt + pip install --require-hashes -r llvm/utils/git/requirements.txt - name: Request Release Note env: diff --git a/.github/workflows/pr-subscriber.yml b/.github/workflows/pr-subscriber.yml index 3952493bb698fe707f75b2ab437a7f8c195bba67..272d3e2f9ef8a31da37ab1301be79227dc23c96c 100644 --- a/.github/workflows/pr-subscriber.yml +++ b/.github/workflows/pr-subscriber.yml @@ -22,7 +22,7 @@ jobs: - name: Setup Automation Script working-directory: ./llvm/utils/git/ run: | - pip install -r requirements.txt + pip install --require-hashes -r requirements.txt - name: Update watchers working-directory: ./llvm/utils/git/ diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml index 02082a84d8c10779f1b8209db580d9ac496551b0..fc497a7de94f7a629c71d0908ed2fbd6193bd4ea 100644 --- a/.github/workflows/release-binaries.yml +++ b/.github/workflows/release-binaries.yml @@ -47,7 +47,7 @@ jobs: - name: Install Dependencies run: | - pip install -r ./llvm/utils/git/requirements.txt + pip install --require-hashes -r ./llvm/utils/git/requirements.txt - name: Check Permissions env: diff --git a/.github/workflows/version-check.yml b/.github/workflows/version-check.yml index c6d779080bbe73b0c15f812556a1d3881f0ba0ef..4ce6119a407f52897b68fcd9efcf3b4ed5a9c862 100644 --- a/.github/workflows/version-check.yml +++ b/.github/workflows/version-check.yml @@ -23,7 +23,7 @@ jobs: - name: Install dependencies run: | - pip install -r ./llvm/utils/git/requirements.txt + pip install --require-hashes -r ./llvm/utils/git/requirements.txt - name: Version Check run: | diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index f7614cf9ac9777be6812e228190cc20c810b4c3d..f7cf538bd0e867eba4f11636b45361a2280c4706 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -438,8 +438,8 @@ public: return false; } - /// Check whether we support inverting this branch - virtual bool isUnsupportedBranch(const MCInst &Inst) const { return false; } + /// Check whether this conditional branch can be reversed + virtual bool isReversibleBranch(const MCInst &Inst) const { return true; } /// Return true of the instruction is of pseudo kind. virtual bool isPseudo(const MCInst &Inst) const { diff --git a/bolt/include/bolt/Profile/DataAggregator.h b/bolt/include/bolt/Profile/DataAggregator.h index f2fa59bcaa1a3ace0d96446bba629992700ea362..c158a9bb3e3f253f5d0e60f4f22c8bb53c42b12b 100644 --- a/bolt/include/bolt/Profile/DataAggregator.h +++ b/bolt/include/bolt/Profile/DataAggregator.h @@ -122,14 +122,14 @@ private: uint64_t ExternCount{0}; }; - struct BranchInfo { + struct TakenBranchInfo { uint64_t TakenCount{0}; uint64_t MispredCount{0}; }; /// Intermediate storage for profile data. We save the results of parsing /// and use them later for processing and assigning profile. - std::unordered_map BranchLBRs; + std::unordered_map BranchLBRs; std::unordered_map FallthroughLBRs; std::vector AggregatedLBRs; std::unordered_map BasicSamples; diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp index 4f44ba0d970c0a0bbbe8b608e291d9e941b567d1..10b93e702984fb180f8d38e652b07340cc5a2846 100644 --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -1284,7 +1284,7 @@ Error BinaryFunction::disassemble() { const bool IsCondBranch = MIB->isConditionalBranch(Instruction); MCSymbol *TargetSymbol = nullptr; - if (BC.MIB->isUnsupportedBranch(Instruction)) { + if (!BC.MIB->isReversibleBranch(Instruction)) { setIgnored(); if (BinaryFunction *TargetFunc = BC.getBinaryFunctionContainingAddress(TargetAddress)) @@ -3381,7 +3381,7 @@ void BinaryFunction::fixBranches() { // Reverse branch condition and swap successors. auto swapSuccessors = [&]() { - if (MIB->isUnsupportedBranch(*CondBranch)) { + if (!MIB->isReversibleBranch(*CondBranch)) { if (opts::Verbosity) { BC.outs() << "BOLT-INFO: unable to swap successors in " << *this << '\n'; diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp index 867f977cebca724c82c2c27729b4492821f72e28..298ba29ff5b3ff0404a9815f2a17cf95efa23ffc 100644 --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -674,7 +674,8 @@ static uint64_t fixDoubleJumps(BinaryFunction &Function, bool MarkInvalid) { MCPlusBuilder *MIB = Function.getBinaryContext().MIB.get(); for (BinaryBasicBlock &BB : Function) { auto checkAndPatch = [&](BinaryBasicBlock *Pred, BinaryBasicBlock *Succ, - const MCSymbol *SuccSym) { + const MCSymbol *SuccSym, + std::optional Offset) { // Ignore infinite loop jumps or fallthrough tail jumps. if (Pred == Succ || Succ == &BB) return false; @@ -715,9 +716,11 @@ static uint64_t fixDoubleJumps(BinaryFunction &Function, bool MarkInvalid) { Pred->removeSuccessor(&BB); Pred->eraseInstruction(Pred->findInstruction(Branch)); Pred->addTailCallInstruction(SuccSym); - MCInst *TailCall = Pred->getLastNonPseudoInstr(); - assert(TailCall); - MIB->setOffset(*TailCall, BB.getOffset()); + if (Offset) { + MCInst *TailCall = Pred->getLastNonPseudoInstr(); + assert(TailCall); + MIB->setOffset(*TailCall, *Offset); + } } else { return false; } @@ -760,7 +763,8 @@ static uint64_t fixDoubleJumps(BinaryFunction &Function, bool MarkInvalid) { if (Pred->getSuccessor() == &BB || (Pred->getConditionalSuccessor(true) == &BB && !IsTailCall) || Pred->getConditionalSuccessor(false) == &BB) - if (checkAndPatch(Pred, Succ, SuccSym) && MarkInvalid) + if (checkAndPatch(Pred, Succ, SuccSym, MIB->getOffset(*Inst)) && + MarkInvalid) BB.markValid(BB.pred_size() != 0 || BB.isLandingPad() || BB.isEntryPoint()); } diff --git a/bolt/lib/Passes/Instrumentation.cpp b/bolt/lib/Passes/Instrumentation.cpp index 68acff7e6a867ccd94180651a6e54f36b83cffe8..14f506f9ca9689ad6ebb9735e24ac5c93b77b72a 100644 --- a/bolt/lib/Passes/Instrumentation.cpp +++ b/bolt/lib/Passes/Instrumentation.cpp @@ -480,7 +480,7 @@ void Instrumentation::instrumentFunction(BinaryFunction &Function, else if (BC.MIB->isUnconditionalBranch(Inst)) HasUnconditionalBranch = true; else if ((!BC.MIB->isCall(Inst) && !BC.MIB->isConditionalBranch(Inst)) || - BC.MIB->isUnsupportedBranch(Inst)) + !BC.MIB->isReversibleBranch(Inst)) continue; const uint32_t FromOffset = *BC.MIB->getOffset(Inst); diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp index 167899ccba1251d3402706644e70a2095a4793b2..e06debcee741e1270cf5f81d4afcc92e25a516f7 100644 --- a/bolt/lib/Profile/DataAggregator.cpp +++ b/bolt/lib/Profile/DataAggregator.cpp @@ -1464,7 +1464,7 @@ uint64_t DataAggregator::parseLBRSample(const PerfBranchSample &Sample, uint64_t To = getBinaryFunctionContainingAddress(LBR.To) ? LBR.To : 0; if (!From && !To) continue; - BranchInfo &Info = BranchLBRs[Trace(From, To)]; + TakenBranchInfo &Info = BranchLBRs[Trace(From, To)]; ++Info.TakenCount; Info.MispredCount += LBR.Mispred; } @@ -1609,7 +1609,7 @@ void DataAggregator::processBranchEvents() { for (const auto &AggrLBR : BranchLBRs) { const Trace &Loc = AggrLBR.first; - const BranchInfo &Info = AggrLBR.second; + const TakenBranchInfo &Info = AggrLBR.second; doBranch(Loc.From, Loc.To, Info.TakenCount, Info.MispredCount); } } @@ -2253,13 +2253,13 @@ DataAggregator::writeAggregatedFile(StringRef OutputFilename) const { } else { for (const auto &KV : NamesToBranches) { const FuncBranchData &FBD = KV.second; - for (const llvm::bolt::BranchInfo &BI : FBD.Data) { + for (const BranchInfo &BI : FBD.Data) { writeLocation(BI.From); writeLocation(BI.To); OutFile << BI.Mispreds << " " << BI.Branches << "\n"; ++BranchValues; } - for (const llvm::bolt::BranchInfo &BI : FBD.EntryData) { + for (const BranchInfo &BI : FBD.EntryData) { // Do not output if source is a known symbol, since this was already // accounted for in the source function if (BI.From.IsSymbol) @@ -2366,7 +2366,7 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC, return std::pair(BlockIt->first, BlockIt->second.getBBIndex()); }; - for (const llvm::bolt::BranchInfo &BI : Branches.Data) { + for (const BranchInfo &BI : Branches.Data) { using namespace yaml::bolt; const auto &[BlockOffset, BlockIndex] = getBlock(BI.From.Offset); BinaryBasicBlockProfile &YamlBB = YamlBF.Blocks[BlockIndex]; @@ -2388,7 +2388,7 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC, } } // Set entry counts, similar to DataReader::readProfile. - for (const llvm::bolt::BranchInfo &BI : Branches.EntryData) { + for (const BranchInfo &BI : Branches.EntryData) { if (!BlockMap.isInputBlock(BI.To.Offset)) { if (opts::Verbosity >= 1) errs() << "BOLT-WARNING: Unexpected EntryData in " << FuncName diff --git a/bolt/lib/Profile/YAMLProfileReader.cpp b/bolt/lib/Profile/YAMLProfileReader.cpp index 978a7cadfe798f63f49e837b30baf4feef402737..29d94067f459fc0500211679083607b4cc8cfcc3 100644 --- a/bolt/lib/Profile/YAMLProfileReader.cpp +++ b/bolt/lib/Profile/YAMLProfileReader.cpp @@ -99,6 +99,9 @@ bool YAMLProfileReader::parseFunctionProfile( FuncRawBranchCount += YamlSI.Count; BF.setRawBranchCount(FuncRawBranchCount); + if (BF.empty()) + return true; + if (!opts::IgnoreHash && YamlBF.Hash != BF.computeHash(IsDFSOrder, HashFunction)) { if (opts::Verbosity >= 1) diff --git a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp index 8b1894953f3757f036aa2d7e58f2f033861b0efd..8fdacffcb147b69ef8306fd915cb4c9929d4cb66 100644 --- a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp +++ b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp @@ -328,19 +328,19 @@ public: return false; } - bool isUnsupportedBranch(const MCInst &Inst) const override { + bool isReversibleBranch(const MCInst &Inst) const override { if (isDynamicBranch(Inst)) - return true; + return false; switch (Inst.getOpcode()) { default: - return false; + return true; case X86::LOOP: case X86::LOOPE: case X86::LOOPNE: case X86::JECXZ: case X86::JRCXZ: - return true; + return false; } } @@ -1874,7 +1874,7 @@ public: } // Handle conditional branches and ignore indirect branches - if (!isUnsupportedBranch(*I) && getCondCode(*I) == X86::COND_INVALID) { + if (isReversibleBranch(*I) && getCondCode(*I) == X86::COND_INVALID) { // Indirect branch return false; } diff --git a/bolt/test/X86/bb-with-two-tail-calls.s b/bolt/test/X86/bb-with-two-tail-calls.s index bb2b0cd4cc23a5bb50a3603d2b8e733b99dda79d..b6703e352ff4bfdd6a29cfc74343c745b826fde6 100644 --- a/bolt/test/X86/bb-with-two-tail-calls.s +++ b/bolt/test/X86/bb-with-two-tail-calls.s @@ -1,8 +1,6 @@ # This reproduces a bug with dynostats when trying to compute branch stats # at a block with two tails calls (one conditional and one unconditional). -# REQUIRES: system-linux - # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \ # RUN: %s -o %t.o # RUN: link_fdata %s %t.o %t.fdata @@ -13,7 +11,7 @@ # CHECK-NOT: Assertion `BranchInfo.size() == 2 && "could only be called for blocks with 2 successors"' failed. # Two tail calls in the same basic block after SCTC: # CHECK: {{.*}}: ja {{.*}} # TAILCALL # Offset: 7 # CTCTakenCount: 4 -# CHECK-NEXT: {{.*}}: jmp {{.*}} # TAILCALL # Offset: 12 +# CHECK-NEXT: {{.*}}: jmp {{.*}} # TAILCALL # Offset: 13 .globl _start _start: @@ -23,7 +21,9 @@ a: ja b x: ret # FDATA: 1 _start #a# 1 _start #b# 2 4 b: jmp e -c: jmp f +c: + .nops 1 + jmp f .globl e e: diff --git a/bolt/test/X86/yaml-non-simple.test b/bolt/test/X86/yaml-non-simple.test new file mode 100644 index 0000000000000000000000000000000000000000..fef98f692a71039f48563b1d5124f26b161c4225 --- /dev/null +++ b/bolt/test/X86/yaml-non-simple.test @@ -0,0 +1,71 @@ +## Check that YAML profile for non-simple function is not reported as stale. + +# RUN: split-file %s %t +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %t/main.s -o %t.o +# RUN: %clang %cflags %t.o -o %t.exe -nostdlib +# RUN: llvm-bolt %t.exe -o %t.out --data %t/yaml --profile-ignore-hash -v=1 \ +# RUN: --report-stale 2>&1 | FileCheck %s + +# CHECK: BOLT-INFO: could not disassemble function main. Will ignore. +# CHECK: BOLT-INFO: could not disassemble function main.cold. Will ignore. +# CHECK: BOLT-INFO: 0 out of 2 functions in the binary (0.0%) have non-empty execution profile +# CHECK: BOLT-INFO: 1 function with profile could not be optimized + +#--- main.s +.globl main +.type main, @function +main: + .cfi_startproc +.LBB00: + pushq %rbp + movq %rsp, %rbp + subq $16, %rsp + testq %rax, %rax + js .LBB03 +.LBB01: + jne .LBB04 +.LBB02: + nop +.LBB03: + xorl %eax, %eax + addq $16, %rsp + popq %rbp + retq +.LBB04: + xorl %eax, %eax + addq $16, %rsp + popq %rbp + retq + .cfi_endproc + .size main, .-main + +.globl main.cold +.type main.cold, @function +main.cold: + .cfi_startproc + nop + .cfi_endproc + .size main.cold, .-main.cold + +#--- yaml +--- +header: + profile-version: 1 + binary-name: 'yaml-non-simple.s.tmp.exe' + binary-build-id: '' + profile-flags: [ lbr ] + profile-origin: branch profile reader + profile-events: '' + dfs-order: false + hash-func: xxh3 +functions: + - name: main + fid: 0 + hash: 0x0000000000000000 + exec: 1 + nblocks: 5 + blocks: + - bid: 1 + insns: 1 + succ: [ { bid: 3, cnt: 1} ] +... diff --git a/clang-tools-extra/clang-query/CMakeLists.txt b/clang-tools-extra/clang-query/CMakeLists.txt index 8a58d4224e049d2485772bf69281ba535e145bc2..34f018c4a03f389c6cb6767f7cf293de64ea9aeb 100644 --- a/clang-tools-extra/clang-query/CMakeLists.txt +++ b/clang-tools-extra/clang-query/CMakeLists.txt @@ -20,7 +20,6 @@ clang_target_link_libraries(clangQuery clangBasic clangDynamicASTMatchers clangFrontend - clangTooling clangSerialization ) diff --git a/clang-tools-extra/clang-query/Query.cpp b/clang-tools-extra/clang-query/Query.cpp index 9d5807a52fa8ed4f6612e8ef9f2ce52c3c65cb66..93f4104d39db8c95b8a840d4e29de278fabb0249 100644 --- a/clang-tools-extra/clang-query/Query.cpp +++ b/clang-tools-extra/clang-query/Query.cpp @@ -13,7 +13,6 @@ #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/TextDiagnostic.h" -#include "clang/Tooling/NodeIntrospection.h" #include "llvm/Support/raw_ostream.h" #include @@ -69,8 +68,6 @@ bool HelpQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { "Diagnostic location for bound nodes.\n" " detailed-ast " "Detailed AST output for bound nodes.\n" - " srcloc " - "Source locations and ranges for bound nodes.\n" " dump " "Detailed AST output for bound nodes (alias of detailed-ast).\n\n"; return true; @@ -91,90 +88,6 @@ struct CollectBoundNodes : MatchFinder::MatchCallback { } }; -void dumpLocations(llvm::raw_ostream &OS, DynTypedNode Node, ASTContext &Ctx, - const DiagnosticsEngine &Diags, SourceManager const &SM) { - auto Locs = clang::tooling::NodeIntrospection::GetLocations(Node); - - auto PrintLocations = [](llvm::raw_ostream &OS, auto Iter, auto End) { - auto CommonEntry = Iter->first; - auto Scout = Iter; - SmallVector LocationStrings; - while (Scout->first == CommonEntry) { - LocationStrings.push_back( - tooling::LocationCallFormatterCpp::format(*Iter->second)); - if (Scout == End) - break; - ++Scout; - if (Scout->first == CommonEntry) - ++Iter; - } - llvm::sort(LocationStrings); - for (auto &LS : LocationStrings) { - OS << " * \"" << LS << "\"\n"; - } - return Iter; - }; - - TextDiagnostic TD(OS, Ctx.getLangOpts(), &Diags.getDiagnosticOptions()); - - for (auto Iter = Locs.LocationAccessors.begin(); - Iter != Locs.LocationAccessors.end(); ++Iter) { - if (!Iter->first.isValid()) - continue; - - TD.emitDiagnostic(FullSourceLoc(Iter->first, SM), DiagnosticsEngine::Note, - "source locations here", std::nullopt, std::nullopt); - - Iter = PrintLocations(OS, Iter, Locs.LocationAccessors.end()); - OS << '\n'; - } - - for (auto Iter = Locs.RangeAccessors.begin(); - Iter != Locs.RangeAccessors.end(); ++Iter) { - - if (!Iter->first.getBegin().isValid()) - continue; - - if (SM.getPresumedLineNumber(Iter->first.getBegin()) != - SM.getPresumedLineNumber(Iter->first.getEnd())) - continue; - - TD.emitDiagnostic( - FullSourceLoc(Iter->first.getBegin(), SM), DiagnosticsEngine::Note, - "source ranges here " + Iter->first.printToString(SM), - CharSourceRange::getTokenRange(Iter->first), std::nullopt); - - Iter = PrintLocations(OS, Iter, Locs.RangeAccessors.end()); - } - for (auto Iter = Locs.RangeAccessors.begin(); - Iter != Locs.RangeAccessors.end(); ++Iter) { - - if (!Iter->first.getBegin().isValid()) - continue; - - if (SM.getPresumedLineNumber(Iter->first.getBegin()) == - SM.getPresumedLineNumber(Iter->first.getEnd())) - continue; - - TD.emitDiagnostic( - FullSourceLoc(Iter->first.getBegin(), SM), DiagnosticsEngine::Note, - "source range " + Iter->first.printToString(SM) + " starting here...", - CharSourceRange::getTokenRange(Iter->first), std::nullopt); - - auto ColNum = SM.getPresumedColumnNumber(Iter->first.getEnd()); - auto LastLineLoc = Iter->first.getEnd().getLocWithOffset(-(ColNum - 1)); - - TD.emitDiagnostic(FullSourceLoc(Iter->first.getEnd(), SM), - DiagnosticsEngine::Note, "... ending here", - CharSourceRange::getTokenRange( - SourceRange(LastLineLoc, Iter->first.getEnd())), - std::nullopt); - - Iter = PrintLocations(OS, Iter, Locs.RangeAccessors.end()); - } - OS << "\n"; -} - } // namespace bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { @@ -195,8 +108,7 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { return false; } - auto &Ctx = AST->getASTContext(); - const auto &SM = Ctx.getSourceManager(); + ASTContext &Ctx = AST->getASTContext(); Ctx.getParentMapContext().setTraversalKind(QS.TK); Finder.matchAST(Ctx); @@ -244,19 +156,11 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { } if (QS.DetailedASTOutput) { OS << "Binding for \"" << BI->first << "\":\n"; - const ASTContext &Ctx = AST->getASTContext(); ASTDumper Dumper(OS, Ctx, AST->getDiagnostics().getShowColors()); Dumper.SetTraversalKind(QS.TK); Dumper.Visit(BI->second); OS << "\n"; } - if (QS.SrcLocOutput) { - OS << "\n \"" << BI->first << "\" Source locations\n"; - OS << " " << std::string(19 + BI->first.size(), '-') << '\n'; - - dumpLocations(OS, BI->second, Ctx, AST->getDiagnostics(), SM); - OS << "\n"; - } } if (MI->getMap().empty()) diff --git a/clang-tools-extra/clang-query/Query.h b/clang-tools-extra/clang-query/Query.h index 7242479633c24f8e94e75ff4ff8e3600e182d2a6..af250fbe13ce3fa72e0b3b729392c5447655538e 100644 --- a/clang-tools-extra/clang-query/Query.h +++ b/clang-tools-extra/clang-query/Query.h @@ -17,7 +17,7 @@ namespace clang { namespace query { -enum OutputKind { OK_Diag, OK_Print, OK_DetailedAST, OK_SrcLoc }; +enum OutputKind { OK_Diag, OK_Print, OK_DetailedAST }; enum QueryKind { QK_Invalid, @@ -149,7 +149,6 @@ struct SetExclusiveOutputQuery : Query { QS.DiagOutput = false; QS.DetailedASTOutput = false; QS.PrintOutput = false; - QS.SrcLocOutput = false; QS.*Var = true; return true; } diff --git a/clang-tools-extra/clang-query/QueryParser.cpp b/clang-tools-extra/clang-query/QueryParser.cpp index 85a442bdd7dedab0318d2d881580401989519c92..1d0b7d9bc6fc84350f0497da542603661a4da3c8 100644 --- a/clang-tools-extra/clang-query/QueryParser.cpp +++ b/clang-tools-extra/clang-query/QueryParser.cpp @@ -11,7 +11,6 @@ #include "QuerySession.h" #include "clang/ASTMatchers/Dynamic/Parser.h" #include "clang/Basic/CharInfo.h" -#include "clang/Tooling/NodeIntrospection.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include @@ -104,19 +103,16 @@ QueryRef QueryParser::parseSetBool(bool QuerySession::*Var) { template QueryRef QueryParser::parseSetOutputKind() { StringRef ValStr; - bool HasIntrospection = tooling::NodeIntrospection::hasIntrospectionSupport(); - unsigned OutKind = - LexOrCompleteWord(this, ValStr) - .Case("diag", OK_Diag) - .Case("print", OK_Print) - .Case("detailed-ast", OK_DetailedAST) - .Case("srcloc", OK_SrcLoc, /*IsCompletion=*/HasIntrospection) - .Case("dump", OK_DetailedAST) - .Default(~0u); + unsigned OutKind = LexOrCompleteWord(this, ValStr) + .Case("diag", OK_Diag) + .Case("print", OK_Print) + .Case("detailed-ast", OK_DetailedAST) + .Case("dump", OK_DetailedAST) + .Default(~0u); if (OutKind == ~0u) { - return new InvalidQuery("expected 'diag', 'print', 'detailed-ast'" + - StringRef(HasIntrospection ? ", 'srcloc'" : "") + - " or 'dump', got '" + ValStr + "'"); + return new InvalidQuery("expected 'diag', 'print', 'detailed-ast' or " + "'dump', got '" + + ValStr + "'"); } switch (OutKind) { @@ -126,10 +122,6 @@ template QueryRef QueryParser::parseSetOutputKind() { return new QueryType(&QuerySession::DiagOutput); case OK_Print: return new QueryType(&QuerySession::PrintOutput); - case OK_SrcLoc: - if (HasIntrospection) - return new QueryType(&QuerySession::SrcLocOutput); - return new InvalidQuery("'srcloc' output support is not available."); } llvm_unreachable("Invalid output kind"); diff --git a/clang-tools-extra/clang-query/QuerySession.h b/clang-tools-extra/clang-query/QuerySession.h index 9a08289a253449193d9a0a0868d8ec93a24dd244..31a4900e26190b13354c5101ef8ddb0fecd61e36 100644 --- a/clang-tools-extra/clang-query/QuerySession.h +++ b/clang-tools-extra/clang-query/QuerySession.h @@ -25,15 +25,14 @@ class QuerySession { public: QuerySession(llvm::ArrayRef> ASTs) : ASTs(ASTs), PrintOutput(false), DiagOutput(true), - DetailedASTOutput(false), SrcLocOutput(false), BindRoot(true), - PrintMatcher(false), Terminate(false), TK(TK_AsIs) {} + DetailedASTOutput(false), BindRoot(true), PrintMatcher(false), + Terminate(false), TK(TK_AsIs) {} llvm::ArrayRef> ASTs; bool PrintOutput; bool DiagOutput; bool DetailedASTOutput; - bool SrcLocOutput; bool BindRoot; bool PrintMatcher; diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 71734617bf7aa8dc5b74596eaae2832cf6fc78a7..6a9892bada9155e4ee87ceef384e1937f0e2cfa9 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -94,6 +94,8 @@ Improvements to clang-query from an external file, allowing the cost of reading the compilation database and building the AST to be imposed just once for faster prototyping. +- Removed support for ``enable output srcloc``. Fixes #GH82591 + Improvements to clang-rename ---------------------------- diff --git a/clang-tools-extra/modularize/ModularizeUtilities.cpp b/clang-tools-extra/modularize/ModularizeUtilities.cpp index 53e8a49d1a54893316d52ed1de4c176a61673e99..b202b3aae8f8a3a5488bb019a30553ef3fa0df2e 100644 --- a/clang-tools-extra/modularize/ModularizeUtilities.cpp +++ b/clang-tools-extra/modularize/ModularizeUtilities.cpp @@ -435,11 +435,9 @@ static std::string replaceDotDot(StringRef Path) { llvm::sys::path::const_iterator B = llvm::sys::path::begin(Path), E = llvm::sys::path::end(Path); while (B != E) { - if (B->compare(".") == 0) { - } - else if (B->compare("..") == 0) + if (*B == "..") llvm::sys::path::remove_filename(Buffer); - else + else if (*B != ".") llvm::sys::path::append(Buffer, *B); ++B; } diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/make-unique.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/make-unique.cpp index 7934c6e93ffbd38a7ae4eaa1b11215172da557a9..fe512a8f3bf3211668961c9da8632783315aeb54 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/make-unique.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/make-unique.cpp @@ -606,11 +606,8 @@ void invoke_template() { template_fun(foo); } -void no_fix_for_invalid_new_loc() { - // FIXME: Although the code is valid, the end location of `new struct Base` is - // invalid. Correct it once https://bugs.llvm.org/show_bug.cgi?id=35952 is - // fixed. +void fix_for_c_style_struct() { auto T = std::unique_ptr(new struct Base); // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::make_unique instead - // CHECK-FIXES: auto T = std::unique_ptr(new struct Base); + // CHECK-FIXES: auto T = std::make_unique(); } diff --git a/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp b/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp index b561e2bb98332113021670dceea19e1104902465..e414587c568b73eadcc56aad35d2e4ffd79ddebe 100644 --- a/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp +++ b/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp @@ -9,7 +9,6 @@ #include "QueryParser.h" #include "Query.h" #include "QuerySession.h" -#include "clang/Tooling/NodeIntrospection.h" #include "llvm/LineEditor/LineEditor.h" #include "gtest/gtest.h" @@ -61,7 +60,6 @@ TEST_F(QueryParserTest, Quit) { TEST_F(QueryParserTest, Set) { - bool HasIntrospection = tooling::NodeIntrospection::hasIntrospectionSupport(); QueryRef Q = parse("set"); ASSERT_TRUE(isa(Q)); EXPECT_EQ("expected variable name", cast(Q)->ErrStr); @@ -72,13 +70,8 @@ TEST_F(QueryParserTest, Set) { Q = parse("set output"); ASSERT_TRUE(isa(Q)); - if (HasIntrospection) - EXPECT_EQ( - "expected 'diag', 'print', 'detailed-ast', 'srcloc' or 'dump', got ''", - cast(Q)->ErrStr); - else - EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got ''", - cast(Q)->ErrStr); + EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got ''", + cast(Q)->ErrStr); Q = parse("set bind-root true foo"); ASSERT_TRUE(isa(Q)); @@ -86,13 +79,8 @@ TEST_F(QueryParserTest, Set) { Q = parse("set output foo"); ASSERT_TRUE(isa(Q)); - if (HasIntrospection) - EXPECT_EQ("expected 'diag', 'print', 'detailed-ast', 'srcloc' or 'dump', " - "got 'foo'", - cast(Q)->ErrStr); - else - EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got 'foo'", - cast(Q)->ErrStr); + EXPECT_EQ("expected 'diag', 'print', 'detailed-ast' or 'dump', got 'foo'", + cast(Q)->ErrStr); Q = parse("set output dump"); ASSERT_TRUE(isa(Q)); @@ -232,10 +220,8 @@ TEST_F(QueryParserTest, Complete) { EXPECT_EQ("output ", Comps[0].TypedText); EXPECT_EQ("output", Comps[0].DisplayText); - bool HasIntrospection = tooling::NodeIntrospection::hasIntrospectionSupport(); - Comps = QueryParser::complete("enable output ", 14, QS); - ASSERT_EQ(HasIntrospection ? 5u : 4u, Comps.size()); + ASSERT_EQ(4u, Comps.size()); EXPECT_EQ("diag ", Comps[0].TypedText); EXPECT_EQ("diag", Comps[0].DisplayText); @@ -243,12 +229,8 @@ TEST_F(QueryParserTest, Complete) { EXPECT_EQ("print", Comps[1].DisplayText); EXPECT_EQ("detailed-ast ", Comps[2].TypedText); EXPECT_EQ("detailed-ast", Comps[2].DisplayText); - if (HasIntrospection) { - EXPECT_EQ("srcloc ", Comps[3].TypedText); - EXPECT_EQ("srcloc", Comps[3].DisplayText); - } - EXPECT_EQ("dump ", Comps[HasIntrospection ? 4 : 3].TypedText); - EXPECT_EQ("dump", Comps[HasIntrospection ? 4 : 3].DisplayText); + EXPECT_EQ("dump ", Comps[3].TypedText); + EXPECT_EQ("dump", Comps[3].DisplayText); Comps = QueryParser::complete("set traversal ", 14, QS); ASSERT_EQ(2u, Comps.size()); diff --git a/clang/cmake/caches/HLSL.cmake b/clang/cmake/caches/HLSL.cmake index 84850c86f12cd7ab92237452ce8b2bd8fdfb0dce..27f848fdccf0ca3e24880f85df20f571f7816d94 100644 --- a/clang/cmake/caches/HLSL.cmake +++ b/clang/cmake/caches/HLSL.cmake @@ -8,6 +8,12 @@ set(LLVM_EXPERIMENTAL_TARGETS_TO_BUILD "DirectX;SPIRV" CACHE STRING "") # HLSL support is currently limted to clang, eventually it will expand to # clang-tools-extra too. -set(LLVM_ENABLE_PROJECTS "clang" CACHE STRING "") +set(LLVM_ENABLE_PROJECTS "clang;clang-tools-extra" CACHE STRING "") set(CLANG_ENABLE_HLSL On CACHE BOOL "") + +if (NOT CMAKE_CONFIGURATION_TYPES) + set(LLVM_DISTRIBUTION_COMPONENTS + "clang;hlsl-resource-headers;clangd" + CACHE STRING "") +endif() diff --git a/clang/docs/HLSL/AvailabilityDiagnostics.rst b/clang/docs/HLSL/AvailabilityDiagnostics.rst new file mode 100644 index 0000000000000000000000000000000000000000..bb9d02f21dde626cf999c6f58818301d8f133c1f --- /dev/null +++ b/clang/docs/HLSL/AvailabilityDiagnostics.rst @@ -0,0 +1,137 @@ +============================= +HLSL Availability Diagnostics +============================= + +.. contents:: + :local: + +Introduction +============ + +HLSL availability diagnostics emits errors or warning when unavailable shader APIs are used. Unavailable shader APIs are APIs that are exposed in HLSL code but are not available in the target shader stage or shader model version. + +There are three modes of HLSL availability diagnostic: + +#. **Default mode** - compiler emits an error when an unavailable API is found in a code that is reachable from the shader entry point function or from an exported library function (when compiling a shader library) + +#. **Relaxed mode** - same as default mode except the compiler emits a warning. This mode is enabled by ``-Wno-error=hlsl-availability``. + +#. **Strict mode** - compiler emits an error when an unavailable API is found in parsed code regardless of whether it can be reached from the shader entry point or exported functions, or not. This mode is enabled by ``-fhlsl-strict-availability``. + +Implementation Details +====================== + +Environment Parameter +--------------------- + +In order to encode API availability based on the shader model version and shader model stage a new ``environment`` parameter was added to the existing Clang ``availability`` attribute. + +The values allowed for this parameter are a subset of values allowed as the ``llvm::Triple`` environment component. If the environment parameters is present, the declared availability attribute applies only to targets with the same platform and environment. + +Default and Relaxed Diagnostic Modes +------------------------------------ + +This mode is implemented in ``DiagnoseHLSLAvailability`` class in ``SemaHLSL.cpp`` and it is invoked after the whole translation unit is parsed (from ``Sema::ActOnEndOfTranslationUnit``). The implementation iterates over all shader entry points and exported library functions in the translation unit and performs an AST traversal of each function body. + +When a reference to another function or member method is found (``DeclRefExpr`` or ``MemberExpr``) and it has a body, the AST of the referenced function is also scanned. This chain of AST traversals will reach all of the code that is reachable from the initial shader entry point or exported library function and avoids the need to generate a call graph. + +All shader APIs have an availability attribute that specifies the shader model version (and environment, if applicable) when this API was first introduced.When a reference to a function without a definition is found and it has an availability attribute, the version of the attribute is checked against the target shader model version and shader stage (if shader stage context is known), and an appropriate diagnostic is generated as needed. + +All shader entry functions have ``HLSLShaderAttr`` attribute that specifies what type of shader this function represents. However, for exported library functions the target shader stage is unknown, so in this case the HLSL API availability will be only checked against the shader model version. It means that for exported library functions the diagnostic of APIs with availability specific to shader stage will be deferred until DXIL linking time. + +A list of functions that were already scanned is kept in order to avoid duplicate scans and diagnostics (see ``DiagnoseHLSLAvailability::ScannedDecls``). It might happen that a shader library has multiple shader entry points for different shader stages that all call into the same shared function. It is therefore important to record not just that a function has been scanned, but also in which shader stage context. This is done by using ``llvm::DenseMap`` that maps ``FunctionDecl *`` to a ``unsigned`` bitmap that represents a set of shader stages (or environments) the function has been scanned for. The ``N``'th bit in the set is set if the function has been scanned in shader environment whose ``HLSLShaderAttr::ShaderType`` integer value equals ``N``. + +The emitted diagnostic messages belong to ``hlsl-availability`` diagnostic group and are reported as errors by default. With ``-Wno-error=hlsl-availability`` flag they become warning, making it relaxed HLSL diagnostics mode. + +Strict Diagnostic Mode +---------------------- + +When strict HLSL availability diagnostic mode is enabled the compiler must report all HLSL API availability issues regardless of code reachability. The implementation of this mode takes advantage of an existing diagnostic scan in ``DiagnoseUnguardedAvailability`` class which is already traversing AST of each function as soon as the function body has been parsed. For HLSL, this pass was only slightly modified, such as making sure diagnostic messages are in the ``hlsl-availability`` group and that availability checks based on shader stage are not included if the shader stage context is unknown. + +If the compilation target is a shader library, only availability based on shader model version can be diagnosed during this scan. To diagnose availability based on shader stage, the compiler needs to run the AST traversals implementated in ``DiagnoseHLSLAvailability`` at the end of the translation unit as described above. + +As a result, availability based on specific shader stage will only be diagnosed in code that is reachable from a shader entry point or library export function. It also means that function bodies might be scanned multiple time. When that happens, care should be taken not to produce duplicated diagnostics. + +======== +Examples +======== + +**Note** +For the example below, the ``WaveActiveCountBits`` API function became available in shader model 6.0 and ``WaveMultiPrefixSum`` in shader model 6.5. + +The availability of ``ddx`` function depends on a shader stage. It is available for pixel shaders in shader model 2.1 and higher, for compute, mesh and amplification shaders in shader model 6.6 and higher. For any other shader stages it is not available. + +Compute shader example +====================== + +.. code-block:: c++ + + float unusedFunction(float f) { + return ddx(f); + } + + [numthreads(4, 4, 1)] + void main(uint3 threadId : SV_DispatchThreadId) { + float f1 = ddx(threadId.x); + float f2 = WaveActiveCountBits(threadId.y == 1.0); + } + +When compiled as compute shader for shader model version 5.0, Clang will emit the following error by default: + +.. code-block:: console + + <>:7:13: error: 'ddx' is only available in compute shader environment on Shader Model 6.6 or newer + <>:8:13: error: 'WaveActiveCountBits' is only available on Shader Model 6.5 or newer + +With relaxed diagnostic mode this errors will become warnings. + +With strict diagnostic mode, in addition to the 2 errors above Clang will also emit error for the ``ddx`` call in ``unusedFunction``.: + +.. code-block:: console + + <>:2:9: error: 'ddx' is only available in compute shader environment on Shader Model 6.5 or newer + <>:7:13: error: 'ddx' is only available in compute shader environment on Shader Model 6.5 or newer + <>:7:13: error: 'WaveActiveCountBits' is only available on Shader Model 6.5 or newer + +Shader library example +====================== + +.. code-block:: c++ + + float myFunction(float f) { + return ddx(f); + } + + float unusedFunction(float f) { + return WaveMultiPrefixSum(f, 1.0); + } + + [shader("compute")] + [numthreads(4, 4, 1)] + void main(uint3 threadId : SV_DispatchThreadId) { + float f = 3; + float e = myFunction(f); + } + + [shader("pixel")] + void main() { + float f = 3; + float e = myFunction(f); + } + +When compiled as shader library vshader model version 6.4, Clang will emit the following error by default: + +.. code-block:: console + + <>:2:9: error: 'ddx' is only available in compute shader environment on Shader Model 6.5 or newer + +With relaxed diagnostic mode this errors will become warnings. + +With strict diagnostic mode Clang will also emit errors for availability issues in code that is not used by any of the entry points: + +.. code-block:: console + + <>2:9: error: 'ddx' is only available in compute shader environment on Shader Model 6.6 or newer + <>:6:9: error: 'WaveActiveCountBits' is only available on Shader Model 6.5 or newer + +Note that ``myFunction`` is reachable from both pixel and compute shader entry points is therefore scanned twice - once for each context. The diagnostic is emitted only for the compute shader context. diff --git a/clang/docs/HLSL/HLSLDocs.rst b/clang/docs/HLSL/HLSLDocs.rst index 97b2425f013b3453cc06b2f61a5846414033880c..1e50a66d984b53b1d39845c2c6a3a7b5b37d6a09 100644 --- a/clang/docs/HLSL/HLSLDocs.rst +++ b/clang/docs/HLSL/HLSLDocs.rst @@ -16,3 +16,4 @@ HLSL Design and Implementation ResourceTypes EntryFunctions FunctionCalls + AvailabilityDiagnostics diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ae699ebfc60383b08662efe4f556ad1bb52b2c6a..a89e10524aa1f20b006abc52e80dd2810f52f5d0 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -51,10 +51,14 @@ C++ Specific Potentially Breaking Changes - The behavior controlled by the `-frelaxed-template-template-args` flag is now on by default, and the flag is deprecated. Until the flag is finally removed, it's negative spelling can be used to obtain compatibility with previous - versions of clang. + versions of clang. The deprecation warning for the negative spelling can be + disabled with `-Wno-deprecated-no-relaxed-template-template-args`. - Clang now rejects pointer to member from parenthesized expression in unevaluated context such as ``decltype(&(foo::bar))``. (#GH40906). +- Clang now performs semantic analysis for unary operators with dependent operands + that are known to be of non-class non-enumeration type prior to instantiation. + ABI Changes in This Version --------------------------- - Fixed Microsoft name mangling of implicitly defined variables used for thread @@ -222,6 +226,9 @@ Resolutions to C++ Defect Reports - Clang now diagnoses declarative nested-name-specifiers with pack-index-specifiers. (`CWG2858: Declarative nested-name-specifiers and pack-index-specifiers `_). +- Clang now allows attributes on concepts. + (`CWG2428: Deprecating a concept `_). + - P0522 implementation is enabled by default in all language versions, and provisional wording for CWG2398 is implemented. @@ -396,6 +403,10 @@ Attribute Changes in Clang - Clang now warns that the ``exclude_from_explicit_instantiation`` attribute is ignored when applied to a local class or a member thereof. +- The ``clspv_libclc_builtin`` attribute has been added to allow clspv + (`OpenCL-C to Vulkan SPIR-V compiler `_) to identify functions coming from libclc + (`OpenCL-C builtin library `_). + Improvements to Clang's diagnostics ----------------------------------- - Clang now applies syntax highlighting to the code snippets it @@ -487,9 +498,15 @@ Improvements to Clang's diagnostics } }; +- Clang emits a ``-Wparentheses`` warning for expressions with consecutive comparisons like ``x < y < z``. + Fixes #GH20456. + Improvements to Clang's time-trace ---------------------------------- +- Clang now specifies that using ``auto`` in a lambda parameter is a C++14 extension when + appropriate. (`#46059: `_). + Bug Fixes in This Version ------------------------- - Clang's ``-Wundefined-func-template`` no longer warns on pure virtual @@ -566,6 +583,12 @@ Bug Fixes in This Version - Clang will no longer emit a duplicate -Wunused-value warning for an expression `(A, B)` which evaluates to glvalue `B` that can be converted to non ODR-use. (#GH45783) +- Clang now correctly disallows VLA type compound literals, e.g. ``(int[size]){}``, + as the C standard mandates. (#GH89835) + +- ``__is_array`` and ``__is_bounded_array`` no longer return ``true`` for + zero-sized arrays. Fixes (#GH54705). + Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -713,6 +736,14 @@ Bug Fixes to C++ Support - Correctly treat the compound statement of an ``if consteval`` as an immediate context. Fixes (#GH91509). - When partial ordering alias templates against template template parameters, allow pack expansions when the alias has a fixed-size parameter list. Fixes (#GH62529). +- Clang now ignores template parameters only used within the exception specification of candidate function + templates during partial ordering when deducing template arguments from a function declaration or when + taking the address of a function template. +- Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). +- Fix a bug where the last argument was not considered when considering the most viable function for + explicit object argument member functions. Fixes (#GH92188). +- Fix a C++11 crash when a non-const non-static member function is defined out-of-line with + the ``constexpr`` specifier. Fixes (#GH61004). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/docs/tools/clang-formatted-files.txt b/clang/docs/tools/clang-formatted-files.txt index eaeadf2656b0bffc5378fcb5d9de2d14048f161c..b747adfb6992e3bc75d17e575457ab47fce07115 100644 --- a/clang/docs/tools/clang-formatted-files.txt +++ b/clang/docs/tools/clang-formatted-files.txt @@ -252,7 +252,6 @@ clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h clang/include/clang/Tooling/DiagnosticsYaml.h clang/include/clang/Tooling/Execution.h clang/include/clang/Tooling/JSONCompilationDatabase.h -clang/include/clang/Tooling/NodeIntrospection.h clang/include/clang/Tooling/Refactoring.h clang/include/clang/Tooling/StandaloneExecution.h clang/include/clang/Tooling/ToolExecutorPluginRegistry.h @@ -562,15 +561,11 @@ clang/lib/Tooling/Execution.cpp clang/lib/Tooling/ExpandResponseFilesCompilationDatabase.cpp clang/lib/Tooling/FixIt.cpp clang/lib/Tooling/GuessTargetAndModeCompilationDatabase.cpp -clang/lib/Tooling/NodeIntrospection.cpp clang/lib/Tooling/StandaloneExecution.cpp clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp clang/lib/Tooling/DependencyScanning/DependencyScanningService.cpp clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp -clang/lib/Tooling/DumpTool/APIData.h -clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.h -clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp clang/lib/Tooling/Inclusions/HeaderIncludes.cpp clang/lib/Tooling/Inclusions/IncludeStyle.cpp clang/lib/Tooling/Inclusions/StandardLibrary.cpp diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index de8b923645f8d6418a1f8a8ae1a5ed80115b8016..5e485ccb85a1391c936b0ec803c96d927caa5033 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -2096,13 +2096,12 @@ private: /// /// \param PointOfInstantiation point at which the function template /// specialization was first instantiated. - void setFunctionTemplateSpecialization(ASTContext &C, - FunctionTemplateDecl *Template, - const TemplateArgumentList *TemplateArgs, - void *InsertPos, - TemplateSpecializationKind TSK, - const TemplateArgumentListInfo *TemplateArgsAsWritten, - SourceLocation PointOfInstantiation); + void setFunctionTemplateSpecialization( + ASTContext &C, FunctionTemplateDecl *Template, + TemplateArgumentList *TemplateArgs, void *InsertPos, + TemplateSpecializationKind TSK, + const TemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation PointOfInstantiation); /// Specify that this record is an instantiation of the /// member function FD. @@ -2981,12 +2980,12 @@ public: /// /// \param PointOfInstantiation point at which the function template /// specialization was first instantiated. - void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, - const TemplateArgumentList *TemplateArgs, - void *InsertPos, - TemplateSpecializationKind TSK = TSK_ImplicitInstantiation, - const TemplateArgumentListInfo *TemplateArgsAsWritten = nullptr, - SourceLocation PointOfInstantiation = SourceLocation()) { + void setFunctionTemplateSpecialization( + FunctionTemplateDecl *Template, TemplateArgumentList *TemplateArgs, + void *InsertPos, + TemplateSpecializationKind TSK = TSK_ImplicitInstantiation, + TemplateArgumentListInfo *TemplateArgsAsWritten = nullptr, + SourceLocation PointOfInstantiation = SourceLocation()) { setFunctionTemplateSpecialization(getASTContext(), Template, TemplateArgs, InsertPos, TSK, TemplateArgsAsWritten, PointOfInstantiation); diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 268aeacf2f20fe2836788b38d2380563754b2fde..f3d6a321ecf104c279a0b855f4e21c46474e7596 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -478,7 +478,7 @@ class FunctionTemplateSpecializationInfo final public: /// The template arguments used to produce the function template /// specialization from the function template. - const TemplateArgumentList *TemplateArguments; + TemplateArgumentList *TemplateArguments; /// The template arguments as written in the sources, if provided. /// FIXME: Normally null; tail-allocate this. @@ -491,7 +491,7 @@ public: private: FunctionTemplateSpecializationInfo( FunctionDecl *FD, FunctionTemplateDecl *Template, - TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs, + TemplateSpecializationKind TSK, TemplateArgumentList *TemplateArgs, const ASTTemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI, MemberSpecializationInfo *MSInfo) : Function(FD, MSInfo ? true : false), Template(Template, TSK - 1), @@ -511,8 +511,7 @@ public: static FunctionTemplateSpecializationInfo * Create(ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template, - TemplateSpecializationKind TSK, - const TemplateArgumentList *TemplateArgs, + TemplateSpecializationKind TSK, TemplateArgumentList *TemplateArgs, const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI, MemberSpecializationInfo *MSInfo); diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 782f60844506f41877e877ec2434547d01059cb0..f5cefedb07e0eba340bd950b3c36769b5a39a774 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -736,13 +736,27 @@ bool RecursiveASTVisitor::TraverseDecl(Decl *D) { // As a syntax visitor, by default we want to ignore declarations for // implicit declarations (ones not typed explicitly by the user). - if (!getDerived().shouldVisitImplicitCode() && D->isImplicit()) { - // For an implicit template type parameter, its type constraints are not - // implicit and are not represented anywhere else. We still need to visit - // them. - if (auto *TTPD = dyn_cast(D)) - return TraverseTemplateTypeParamDeclConstraints(TTPD); - return true; + if (!getDerived().shouldVisitImplicitCode()) { + if (D->isImplicit()) { + // For an implicit template type parameter, its type constraints are not + // implicit and are not represented anywhere else. We still need to visit + // them. + if (auto *TTPD = dyn_cast(D)) + return TraverseTemplateTypeParamDeclConstraints(TTPD); + return true; + } + + // Deduction guides for alias templates are always synthesized, so they + // should not be traversed unless shouldVisitImplicitCode() returns true. + // + // It's important to note that checking the implicit bit is not efficient + // for the alias case. For deduction guides synthesized from explicit + // user-defined deduction guides, we must maintain the explicit bit to + // ensure correct overload resolution. + if (auto *FTD = dyn_cast(D)) + if (llvm::isa_and_present( + FTD->getDeclName().getCXXDeductionGuideTemplate())) + return true; } switch (D->getKind()) { diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index e6643469e0b3344937d69beeee77e37d8bfed37e..da3834f19ca04466ab9574c8fdbcfd737539bcfe 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -8044,7 +8044,10 @@ inline bool Type::isUndeducedType() const { /// Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { - return isDependentType() || isRecordType() || isEnumeralType(); + if (!CanonicalType->isDependentType()) + return isRecordType() || isEnumeralType(); + return !isArrayType() && !isFunctionType() && !isAnyPointerType() && + !isMemberPointerType(); } /// Determines whether this type is written as a typedef-name. diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h index 5d16dcc824c50c581b7a109d8d0fa9f9b3b19886..228b4ae1e3e1155008c33cd0691e36a63b155744 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h @@ -106,6 +106,11 @@ public: virtual void handleUnsafeOperation(const Stmt *Operation, bool IsRelatedToDecl, ASTContext &Ctx) = 0; + /// Invoked when an unsafe operation with a std container is found. + virtual void handleUnsafeOperationInContainer(const Stmt *Operation, + bool IsRelatedToDecl, + ASTContext &Ctx) = 0; + /// Invoked when a fix is suggested against a variable. This function groups /// all variables that must be fixed together (i.e their types must be changed /// to the same target type to prevent type mismatches) into a single fixit. diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index 3273c642eed517cacbd16252fc78f79e656a5de2..242ad763ba62b9a806f605f97022a8280ad3d152 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ WARNING_GADGET(Decrement) WARNING_GADGET(ArraySubscript) WARNING_GADGET(PointerArithmetic) WARNING_GADGET(UnsafeBufferUsageAttr) +WARNING_GADGET(UnsafeBufferUsageCtorAttr) WARNING_GADGET(DataInvocation) WARNING_CONTAINER_GADGET(SpanTwoParamConstructor) // Uses of `std::span(arg0, arg1)` FIXABLE_GADGET(ULCArraySubscript) // `DRE[any]` in an Unspecified Lvalue Context diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index cdf89c7def2c9185803af843f14fcbd88e59f5f5..097ff2bdfe7ada5a89e3842cbc848fcdd5df4ad4 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -19,6 +19,7 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/Expr.h" #include "clang/AST/Type.h" +#include "clang/Analysis/FlowSensitive/ASTOps.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" #include "clang/Analysis/FlowSensitive/DataflowLattice.h" #include "clang/Analysis/FlowSensitive/Formula.h" @@ -30,9 +31,11 @@ #include "llvm/ADT/MapVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include #include #include #include +#include namespace clang { namespace dataflow { @@ -155,7 +158,28 @@ public: /// Creates an environment that uses `DACtx` to store objects that encompass /// the state of a program. - explicit Environment(DataflowAnalysisContext &DACtx); + explicit Environment(DataflowAnalysisContext &DACtx) + : DACtx(&DACtx), + FlowConditionToken(DACtx.arena().makeFlowConditionToken()) {} + + /// Creates an environment that uses `DACtx` to store objects that encompass + /// the state of a program, with `S` as the statement to analyze. + Environment(DataflowAnalysisContext &DACtx, Stmt &S) : Environment(DACtx) { + InitialTargetStmt = &S; + } + + /// Creates an environment that uses `DACtx` to store objects that encompass + /// the state of a program, with `FD` as the function to analyze. + /// + /// Requirements: + /// + /// The function must have a body, i.e. + /// `FunctionDecl::doesThisDecalarationHaveABody()` must be true. + Environment(DataflowAnalysisContext &DACtx, const FunctionDecl &FD) + : Environment(DACtx, *FD.getBody()) { + assert(FD.doesThisDeclarationHaveABody()); + InitialTargetFunc = &FD; + } // Copy-constructor is private, Environments should not be copied. See fork(). Environment &operator=(const Environment &Other) = delete; @@ -163,24 +187,11 @@ public: Environment(Environment &&Other) = default; Environment &operator=(Environment &&Other) = default; - /// Creates an environment that uses `DACtx` to store objects that encompass - /// the state of a program. - /// - /// If `DeclCtx` is a function, initializes the environment with symbolic - /// representations of the function parameters. - /// - /// If `DeclCtx` is a non-static member function, initializes the environment - /// with a symbolic representation of the `this` pointee. - Environment(DataflowAnalysisContext &DACtx, const DeclContext &DeclCtx); - /// Assigns storage locations and values to all parameters, captures, global - /// variables, fields and functions referenced in the function currently being - /// analyzed. - /// - /// Requirements: + /// variables, fields and functions referenced in the `Stmt` or `FunctionDecl` + /// passed to the constructor. /// - /// The function must have a body, i.e. - /// `FunctionDecl::doesThisDecalarationHaveABody()` must be true. + /// If no `Stmt` or `FunctionDecl` was supplied, this function does nothing. void initialize(); /// Returns a new environment that is a copy of this one. @@ -193,7 +204,7 @@ public: /// forked flow condition references the original). Environment fork() const; - /// Creates and returns an environment to use for an inline analysis of the + /// Creates and returns an environment to use for an inline analysis of the /// callee. Uses the storage location from each argument in the `Call` as the /// storage location for the corresponding parameter in the callee. /// @@ -365,46 +376,51 @@ public: RecordStorageLocation & getResultObjectLocation(const Expr &RecordPRValue) const; - /// Returns the return value of the current function. This can be null if: + /// Returns the return value of the function currently being analyzed. + /// This can be null if: /// - The function has a void return type /// - No return value could be determined for the function, for example /// because it calls a function without a body. /// /// Requirements: - /// The current function must have a non-reference return type. + /// The current analysis target must be a function and must have a + /// non-reference return type. Value *getReturnValue() const { assert(getCurrentFunc() != nullptr && !getCurrentFunc()->getReturnType()->isReferenceType()); return ReturnVal; } - /// Returns the storage location for the reference returned by the current - /// function. This can be null if function doesn't return a single consistent - /// reference. + /// Returns the storage location for the reference returned by the function + /// currently being analyzed. This can be null if the function doesn't return + /// a single consistent reference. /// /// Requirements: - /// The current function must have a reference return type. + /// The current analysis target must be a function and must have a reference + /// return type. StorageLocation *getReturnStorageLocation() const { assert(getCurrentFunc() != nullptr && getCurrentFunc()->getReturnType()->isReferenceType()); return ReturnLoc; } - /// Sets the return value of the current function. + /// Sets the return value of the function currently being analyzed. /// /// Requirements: - /// The current function must have a non-reference return type. + /// The current analysis target must be a function and must have a + /// non-reference return type. void setReturnValue(Value *Val) { assert(getCurrentFunc() != nullptr && !getCurrentFunc()->getReturnType()->isReferenceType()); ReturnVal = Val; } - /// Sets the storage location for the reference returned by the current - /// function. + /// Sets the storage location for the reference returned by the function + /// currently being analyzed. /// /// Requirements: - /// The current function must have a reference return type. + /// The current analysis target must be a function and must have a reference + /// return type. void setReturnStorageLocation(StorageLocation *Loc) { assert(getCurrentFunc() != nullptr && getCurrentFunc()->getReturnType()->isReferenceType()); @@ -641,23 +657,21 @@ public: /// (or the flow condition is overly constraining) or if the solver times out. bool allows(const Formula &) const; - /// Returns the `DeclContext` of the block being analysed, if any. Otherwise, - /// returns null. - const DeclContext *getDeclCtx() const { return CallStack.back(); } - /// Returns the function currently being analyzed, or null if the code being /// analyzed isn't part of a function. const FunctionDecl *getCurrentFunc() const { - return dyn_cast(getDeclCtx()); + return CallStack.empty() ? InitialTargetFunc : CallStack.back(); } - /// Returns the size of the call stack. + /// Returns the size of the call stack, not counting the initial analysis + /// target. size_t callStackSize() const { return CallStack.size(); } /// Returns whether this `Environment` can be extended to analyze the given - /// `Callee` (i.e. if `pushCall` can be used), with recursion disallowed and a - /// given `MaxDepth`. - bool canDescend(unsigned MaxDepth, const DeclContext *Callee) const; + /// `Callee` (i.e. if `pushCall` can be used). + /// Recursion is not allowed. `MaxDepth` is the maximum size of the call stack + /// (i.e. the maximum value that `callStackSize()` may assume after the call). + bool canDescend(unsigned MaxDepth, const FunctionDecl *Callee) const; /// Returns the `DataflowAnalysisContext` used by the environment. DataflowAnalysisContext &getDataflowAnalysisContext() const { return *DACtx; } @@ -719,8 +733,8 @@ private: ArrayRef Args); /// Assigns storage locations and values to all global variables, fields - /// and functions referenced in `FuncDecl`. `FuncDecl` must have a body. - void initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl); + /// and functions in `Referenced`. + void initFieldsGlobalsAndFuncs(const ReferencedDecls &Referenced); static PrValueToResultObject buildResultObjectMap(DataflowAnalysisContext *DACtx, @@ -728,6 +742,11 @@ private: RecordStorageLocation *ThisPointeeLoc, RecordStorageLocation *LocForRecordReturnVal); + static PrValueToResultObject + buildResultObjectMap(DataflowAnalysisContext *DACtx, Stmt *S, + RecordStorageLocation *ThisPointeeLoc, + RecordStorageLocation *LocForRecordReturnVal); + // `DACtx` is not null and not owned by this object. DataflowAnalysisContext *DACtx; @@ -736,11 +755,20 @@ private: // shared between environments in the same call. // https://github.com/llvm/llvm-project/issues/59005 - // `DeclContext` of the block being analysed if provided. - std::vector CallStack; + // The stack of functions called from the initial analysis target. + std::vector CallStack; + + // Initial function to analyze, if a function was passed to the constructor. + // Null otherwise. + const FunctionDecl *InitialTargetFunc = nullptr; + // Top-level statement of the initial analysis target. + // If a function was passed to the constructor, this is its body. + // If a statement was passed to the constructor, this is that statement. + // Null if no analysis target was passed to the constructor. + Stmt *InitialTargetStmt = nullptr; // Maps from prvalues of record type to their result objects. Shared between - // all environments for the same function. + // all environments for the same analysis target. // FIXME: It's somewhat unsatisfactory that we have to use a `shared_ptr` // here, though the cost is acceptable: The overhead of a `shared_ptr` is // incurred when it is copied, and this happens only relatively rarely (when @@ -749,7 +777,7 @@ private: std::shared_ptr ResultObjectMap; // The following three member variables handle various different types of - // return values. + // return values when the current analysis target is a function. // - If the return type is not a reference and not a record: Value returned // by the function. Value *ReturnVal = nullptr; @@ -762,7 +790,7 @@ private: RecordStorageLocation *LocForRecordReturnVal = nullptr; // The storage location of the `this` pointee. Should only be null if the - // function being analyzed is only a function and not a method. + // analysis target is not a method. RecordStorageLocation *ThisPointeeLoc = nullptr; // Maps from declarations and glvalue expression to storage locations that are diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 52552ba488560b2462139026789e564ac0387bda..7008bea483c8723ee70efce35f207972fcaadea3 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -999,7 +999,7 @@ def Availability : InheritableAttr { VersionArgument<"deprecated">, VersionArgument<"obsoleted">, BoolArgument<"unavailable">, StringArgument<"message">, BoolArgument<"strict">, StringArgument<"replacement">, - IntArgument<"priority">]; + IntArgument<"priority">, IdentifierArgument<"environment">]; let AdditionalMembers = [{static llvm::StringRef getPrettyPlatformName(llvm::StringRef Platform) { return llvm::StringSwitch(Platform) @@ -1019,7 +1019,7 @@ def Availability : InheritableAttr { .Case("xros", "visionOS") .Case("xros_app_extension", "visionOS (App Extension)") .Case("swift", "Swift") - .Case("shadermodel", "HLSL ShaderModel") + .Case("shadermodel", "Shader Model") .Case("ohos", "OpenHarmony OS") .Default(llvm::StringRef()); } @@ -1059,7 +1059,34 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) { .Case("visionos_app_extension", "xros_app_extension") .Case("ShaderModel", "shadermodel") .Default(Platform); -} }]; +} +static llvm::StringRef getPrettyEnviromentName(llvm::StringRef Environment) { + return llvm::StringSwitch(Environment) + .Case("pixel", "pixel shader") + .Case("vertex", "vertex shader") + .Case("geometry", "geometry shader") + .Case("hull", "hull shader") + .Case("domain", "domain shader") + .Case("compute", "compute shader") + .Case("mesh", "mesh shader") + .Case("amplification", "amplification shader") + .Case("library", "shader library") + .Default(Environment); +} +static llvm::Triple::EnvironmentType getEnvironmentType(llvm::StringRef Environment) { + return llvm::StringSwitch(Environment) + .Case("pixel", llvm::Triple::Pixel) + .Case("vertex", llvm::Triple::Vertex) + .Case("geometry", llvm::Triple::Geometry) + .Case("hull", llvm::Triple::Hull) + .Case("domain", llvm::Triple::Domain) + .Case("compute", llvm::Triple::Compute) + .Case("mesh", llvm::Triple::Mesh) + .Case("amplification", llvm::Triple::Amplification) + .Case("library", llvm::Triple::Library) + .Default(llvm::Triple::UnknownEnvironment); +} +}]; let HasCustomParsing = 1; let InheritEvenIfAlreadyPresent = 1; let Subjects = SubjectList<[Named]>; @@ -4561,3 +4588,10 @@ def CodeAlign: StmtAttr { static constexpr int MaximumAlignment = 4096; }]; } + +def ClspvLibclcBuiltin: InheritableAttr { + let Spellings = [Clang<"clspv_libclc_builtin">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [ClspvLibclcBuiltinDoc]; + let SimpleHandler = 1; +} diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index f351822ac74bd5a451d951305dbfcc6c64c95f55..54197d588eb45084e93e3d8b5eeec277feeee035 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -1593,6 +1593,11 @@ replacement=\ *string-literal* a warning about use of a deprecated declaration. The Fix-It will replace the deprecated declaration with the new declaration specified. +environment=\ *identifier* + Target environment in which this declaration is available. If present, + the availability attribute applies only to targets with the same platform + and environment. The parameter is currently supported only in HLSL. + Multiple availability attributes can be placed on a declaration, which may correspond to different platforms. For most platforms, the availability attribute with the platform corresponding to the target platform will be used; @@ -8087,3 +8092,17 @@ requirement: } }]; } + +def ClspvLibclcBuiltinDoc : Documentation { + let Category = DocCatFunction; + let Content = [{ +Attribute used by `clspv`_ (OpenCL-C to Vulkan SPIR-V compiler) to identify functions coming from `libclc`_ (OpenCL-C builtin library). + +.. code-block:: c + + void __attribute__((clspv_libclc_builtin)) libclc_builtin() {} + +.. _`clspv`: https://github.com/google/clspv +.. _`libclc`: https://libclc.llvm.org +}]; +} diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 9781fcaa4ff5e913e619d347a2c5d2a98940bd9d..9d97a75f696f668ac858ce08919b2f7339150d1f 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -436,6 +436,9 @@ def warn_drv_clang_unsupported : Warning< "the clang compiler does not support '%0'">; def warn_drv_deprecated_arg : Warning< "argument '%0' is deprecated%select{|, use '%2' instead}1">, InGroup; +def warn_drv_deprecated_arg_no_relaxed_template_template_args : Warning< + "argument '-fno-relaxed-template-template-args' is deprecated">, + InGroup; def warn_drv_deprecated_custom : Warning< "argument '%0' is deprecated, %1">, InGroup; def warn_drv_assuming_mfloat_abi_is : Warning< diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 2beb1d45124b4945f6c4fa7d254380673b5f7d8e..4cb4f3d999f7ab466de3794c11bb7692109ee801 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -104,6 +104,7 @@ def EnumConversion : DiagGroup<"enum-conversion", [EnumEnumConversion, EnumFloatConversion, EnumCompareConditional]>; +def DeprecatedNoRelaxedTemplateTemplateArgs : DiagGroup<"deprecated-no-relaxed-template-template-args">; def ObjCSignedCharBoolImplicitIntConversion : DiagGroup<"objc-signed-char-bool-implicit-int-conversion">; def Shorten64To32 : DiagGroup<"shorten-64-to-32">; @@ -228,6 +229,7 @@ def Deprecated : DiagGroup<"deprecated", [DeprecatedAnonEnumEnumConversion, DeprecatedLiteralOperator, DeprecatedPragma, DeprecatedRegister, + DeprecatedNoRelaxedTemplateTemplateArgs, DeprecatedThisCapture, DeprecatedType, DeprecatedVolatile, diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 8316845844cb2e60ab8386ae3003905cfd36a96d..46656fc66044d21d483f5679a74f1dd458c00806 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1112,6 +1112,8 @@ def err_zero_version : Error< "version number must have non-zero major, minor, or sub-minor version">; def err_availability_expected_platform : Error< "expected a platform name, e.g., 'macos'">; +def err_availability_expected_environment : Error< + "expected an environment name, e.g., 'compute'">; // objc_bridge_related attribute def err_objcbridge_related_expected_related_class : Error< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6100fba5100590b3b83fc9733533415b65e307e2..e3b4186f1b06fadaea7c8a12a5761322b643a472 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2433,7 +2433,9 @@ def err_auto_not_allowed : Error< "|in template parameter|in friend declaration|in function prototype that is " "not a function declaration|in requires expression parameter" "|in array declaration" - "|in declaration of conversion function template}1">; + "|in declaration of conversion function template" + "|in lambda parameter before C++14}1">; + def err_dependent_deduced_tst : Error< "typename specifier refers to " "%select{class template|function template|variable template|alias template|" @@ -3003,6 +3005,8 @@ def note_single_arg_concept_specialization_constraint_evaluated_to_false : Note< "%select{and|because}0 %1 does not satisfy %2">; def note_atomic_constraint_evaluated_to_false_elaborated : Note< "%select{and|because}0 '%1' (%2 %3 %4) evaluated to false">; +def note_is_deducible_constraint_evaluated_to_false : Note< + "cannot deduce template arguments for %0 from %1">; def err_constrained_virtual_method : Error< "virtual function cannot have a requires clause">; def err_trailing_requires_clause_on_deduction_guide : Error< @@ -3205,6 +3209,8 @@ def warn_attribute_arm_zt0_builtin_no_zt0_state : Warning< InGroup>; def err_sve_vector_in_non_sve_target : Error< "SVE vector type %0 cannot be used in a target without sve">; +def err_sve_vector_in_non_streaming_function : Error< + "SVE vector type %0 cannot be used in a non-streaming function">; def err_attribute_riscv_rvv_bits_unsupported : Error< "%0 is only supported when '-mrvv-vector-bits=' is specified with a " "value of \"zvl\" or a power 2 in the range [64,65536]">; @@ -3371,6 +3377,8 @@ def err_field_with_address_space : Error< "field may not be qualified with an address space">; def err_compound_literal_with_address_space : Error< "compound literal in function scope may not be qualified with an address space">; +def err_compound_literal_with_vla_type : Error< + "compound literal cannot be of variable-length array type">; def err_address_space_mismatch_templ_inst : Error< "conflicting address space qualifiers are provided between types %0 and %1">; def err_attr_objc_ownership_redundant : Error< @@ -3829,6 +3837,9 @@ def note_cannot_use_trivial_abi_reason : Note< // Availability attribute def warn_availability_unknown_platform : Warning< "unknown platform %0 in availability macro">, InGroup; +def warn_availability_unknown_environment : Warning< + "unknown environment %0 in availability macro">, InGroup; + def warn_availability_version_ordering : Warning< "feature cannot be %select{introduced|deprecated|obsoleted}0 in %1 version " "%2 before it was %select{introduced|deprecated|obsoleted}3 in version %4; " @@ -3859,13 +3870,21 @@ def note_protocol_method : Note< def warn_availability_fuchsia_unavailable_minor : Warning< "Fuchsia API Level prohibits specifying a minor or sub-minor version">, InGroup; +def err_availability_unexpected_parameter: Error< + "unexpected parameter '%0' in availability attribute, not permitted in %select{HLSL|C/C++}1">; def warn_unguarded_availability : - Warning<"%0 is only available on %1 %2 or newer">, + Warning<"%0 is only available %select{|in %4 environment }3on %1 %2 or newer">, + InGroup, DefaultIgnore; +def warn_unguarded_availability_unavailable : + Warning<"%0 is unavailable">, InGroup, DefaultIgnore; def warn_unguarded_availability_new : Warning, InGroup; +def warn_unguarded_availability_unavailable_new : + Warning, + InGroup; def note_decl_unguarded_availability_silence : Note< "annotate %select{%1|anonymous %1}0 with an availability attribute to silence this warning">; def note_unguarded_available_silence : Note< @@ -5862,8 +5881,8 @@ def note_availability_specified_here : Note< "%0 has been explicitly marked " "%select{unavailable|deleted|deprecated}1 here">; def note_partial_availability_specified_here : Note< - "%0 has been marked as being introduced in %1 %2 here, " - "but the deployment target is %1 %3">; + "%0 has been marked as being introduced in %1 %2 %select{|in %5 environment }4here, " + "but the deployment target is %1 %3%select{| %6 environment }4">; def note_implicitly_deleted : Note< "explicitly defaulted function was implicitly deleted here">; def warn_not_enough_argument : Warning< @@ -6911,6 +6930,10 @@ def warn_precedence_bitwise_conditional : Warning< def note_precedence_conditional_first : Note< "place parentheses around the '?:' expression to evaluate it first">; +def warn_consecutive_comparison : Warning< + "comparisons like 'X<=Y<=Z' don't have their mathematical meaning">, + InGroup; + def warn_enum_constant_in_bool_context : Warning< "converting the enum constant to a boolean">, InGroup, DefaultIgnore; @@ -10035,6 +10058,12 @@ def warn_new_dangling_initializer_list : Warning< "the allocated initializer list}0 " "will be destroyed at the end of the full-expression">, InGroup; +def warn_unsupported_lifetime_extension : Warning< + "lifetime extension of " + "%select{temporary|backing array of initializer list}0 created " + "by aggregate initialization using a default member initializer " + "is not yet supported; lifetime of %select{temporary|backing array}0 " + "will end at the end of the full-expression">, InGroup; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index 5258bab584f49f6d477ac467b9fa285ba064ae06..ce33423551039c0acc94ff597bfd5ecb3f6a1b0a 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -497,6 +497,10 @@ public: bool isFile() const { return !isExpansion(); } const FileInfo &getFile() const { + return const_cast(this)->getFile(); + } + + FileInfo &getFile() { assert(isFile() && "Not a file SLocEntry!"); return File; } @@ -1120,12 +1124,12 @@ public: /// Set the number of FileIDs (files and macros) that were created /// during preprocessing of \p FID, including it. void setNumCreatedFIDsForFileID(FileID FID, unsigned NumFIDs, - bool Force = false) const { + bool Force = false) { auto *Entry = getSLocEntryForFile(FID); if (!Entry) return; assert((Force || Entry->getFile().NumCreatedFIDs == 0) && "Already set!"); - const_cast(Entry->getFile()).NumCreatedFIDs = NumFIDs; + Entry->getFile().NumCreatedFIDs = NumFIDs; } //===--------------------------------------------------------------------===// @@ -1730,6 +1734,11 @@ public: /// Get a local SLocEntry. This is exposed for indexing. const SrcMgr::SLocEntry &getLocalSLocEntry(unsigned Index) const { + return const_cast(this)->getLocalSLocEntry(Index); + } + + /// Get a local SLocEntry. This is exposed for indexing. + SrcMgr::SLocEntry &getLocalSLocEntry(unsigned Index) { assert(Index < LocalSLocEntryTable.size() && "Invalid index"); return LocalSLocEntryTable[Index]; } @@ -1740,6 +1749,13 @@ public: /// Get a loaded SLocEntry. This is exposed for indexing. const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index, bool *Invalid = nullptr) const { + return const_cast(this)->getLoadedSLocEntry(Index, + Invalid); + } + + /// Get a loaded SLocEntry. This is exposed for indexing. + SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index, + bool *Invalid = nullptr) { assert(Index < LoadedSLocEntryTable.size() && "Invalid index"); if (SLocEntryLoaded[Index]) return LoadedSLocEntryTable[Index]; @@ -1748,6 +1764,10 @@ public: const SrcMgr::SLocEntry &getSLocEntry(FileID FID, bool *Invalid = nullptr) const { + return const_cast(this)->getSLocEntry(FID, Invalid); + } + + SrcMgr::SLocEntry &getSLocEntry(FileID FID, bool *Invalid = nullptr) { if (FID.ID == 0 || FID.ID == -1) { if (Invalid) *Invalid = true; return LocalSLocEntryTable[0]; @@ -1821,14 +1841,23 @@ private: SrcMgr::ContentCache &getFakeContentCacheForRecovery() const; const SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid) const; + SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid); const SrcMgr::SLocEntry *getSLocEntryOrNull(FileID FID) const { + return const_cast(this)->getSLocEntryOrNull(FID); + } + + SrcMgr::SLocEntry *getSLocEntryOrNull(FileID FID) { bool Invalid = false; - const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); + SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); return Invalid ? nullptr : &Entry; } const SrcMgr::SLocEntry *getSLocEntryForFile(FileID FID) const { + return const_cast(this)->getSLocEntryForFile(FID); + } + + SrcMgr::SLocEntry *getSLocEntryForFile(FileID FID) { if (auto *Entry = getSLocEntryOrNull(FID)) if (Entry->isFile()) return Entry; @@ -1839,6 +1868,10 @@ private: /// Invalid will not be modified for Local IDs. const SrcMgr::SLocEntry &getSLocEntryByID(int ID, bool *Invalid = nullptr) const { + return const_cast(this)->getSLocEntryByID(ID, Invalid); + } + + SrcMgr::SLocEntry &getSLocEntryByID(int ID, bool *Invalid = nullptr) { assert(ID != -1 && "Using FileID sentinel value"); if (ID < 0) return getLoadedSLocEntryByID(ID, Invalid); @@ -1847,6 +1880,11 @@ private: const SrcMgr::SLocEntry & getLoadedSLocEntryByID(int ID, bool *Invalid = nullptr) const { + return const_cast(this)->getLoadedSLocEntryByID(ID, + Invalid); + } + + SrcMgr::SLocEntry &getLoadedSLocEntryByID(int ID, bool *Invalid = nullptr) { return getLoadedSLocEntry(static_cast(-ID - 2), Invalid); } diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 56c4b17f769d7039a345967fe06da5b0875a5461..b5a0e9df9f7aeea1301250f5308a11d8799e0708 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -538,6 +538,9 @@ TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX) TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) TYPE_TRAIT_2(__reference_constructs_from_temporary, ReferenceConstructsFromTemporary, KEYCXX) TYPE_TRAIT_2(__reference_converts_from_temporary, ReferenceConvertsFromTemporary, KEYCXX) +// IsDeducible is only used internally by clang for CTAD implementation and +// is not exposed to users. +TYPE_TRAIT_2(/*EmptySpellingName*/, IsDeducible, KEYCXX) // Embarcadero Expression Traits EXPRESSION_TRAIT(__is_lvalue_expr, IsLValueExpr, KEYCXX) diff --git a/clang/include/clang/Basic/arm_sme.td b/clang/include/clang/Basic/arm_sme.td index 7808ee559932ec78f4e74044e5c9dca83b610ae6..80e635e4a57eca78ac1413ced1d49f5a5da7a22a 100644 --- a/clang/include/clang/Basic/arm_sme.td +++ b/clang/include/clang/Basic/arm_sme.td @@ -298,6 +298,16 @@ multiclass ZAAddSub { def NAME # _ZA64_VG1X2_F64 : Inst<"sv" # n_suffix # "_za64[_{d}]_vg1x2", "vm2", "d", MergeNone, "aarch64_sme_" # n_suffix # "_za64_vg1x2", [IsStreaming, IsInOutZA], []>; def NAME # _ZA64_VG1X4_F64 : Inst<"sv" # n_suffix # "_za64[_{d}]_vg1x4", "vm4", "d", MergeNone, "aarch64_sme_" # n_suffix # "_za64_vg1x4", [IsStreaming, IsInOutZA], []>; } + + let TargetGuard = "sme-f16f16|sme-f8f16" in { + def NAME # _ZA16_VG1X2_F16 : Inst<"sv" # n_suffix # "_za16[_{d}]_vg1x2", "vm2", "h", MergeNone, "aarch64_sme_" # n_suffix # "_za16_vg1x2", [IsStreaming, IsInOutZA], []>; + def NAME # _ZA16_VG1X4_F16 : Inst<"sv" # n_suffix # "_za16[_{d}]_vg1x4", "vm4", "h", MergeNone, "aarch64_sme_" # n_suffix # "_za16_vg1x4", [IsStreaming, IsInOutZA], []>; + } + + let TargetGuard = "sme2,b16b16" in { + def NAME # _ZA16_VG1X2_BF16 : Inst<"sv" # n_suffix # "_za16[_{d}]_vg1x2", "vm2", "b", MergeNone, "aarch64_sme_" # n_suffix # "_za16_vg1x2", [IsStreaming, IsInOutZA], []>; + def NAME # _ZA16_VG1X4_BF16 : Inst<"sv" # n_suffix # "_za16[_{d}]_vg1x4", "vm4", "b", MergeNone, "aarch64_sme_" # n_suffix # "_za16_vg1x4", [IsStreaming, IsInOutZA], []>; + } } defm SVADD : ZAAddSub<"add">; diff --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td index 15340ebb62b365d1ea8d7a40811097a49aaa5e26..a9ea71cd077740d4fff1bb8f0d3951d14030addb 100644 --- a/clang/include/clang/Basic/arm_sve.td +++ b/clang/include/clang/Basic/arm_sve.td @@ -2095,7 +2095,7 @@ def SVFCLAMP_BF : SInst<"svclamp[_{d}]", "dddd", "b", MergeNone, "aarch64_sve_ multiclass MinMaxIntr { def SVS # NAME : SInst<"sv" # i # "[" # zm # "_{d}_" # mul # "]", t, "csil", MergeNone, "aarch64_sve_s" # i # zm # "_" # mul, [IsStreaming], []>; def SVU # NAME : SInst<"sv" # i # "[" # zm # "_{d}_" # mul # "]", t, "UcUsUiUl", MergeNone, "aarch64_sve_u" # i # zm # "_" # mul, [IsStreaming], []>; - def SVF # NAME : SInst<"sv" # i # "[" # zm # "_{d}_" # mul # "]", t, "hfd", MergeNone, "aarch64_sve_f" # i # zm # "_" # mul, [IsStreaming], []>; + def SVF # NAME : SInst<"sv" # i # "[" # zm # "_{d}_" # mul # "]", t, "bhfd", MergeNone, "aarch64_sve_f" # i # zm # "_" # mul, [IsStreaming], []>; } let TargetGuard = "sme2" in { @@ -2113,11 +2113,11 @@ let TargetGuard = "sme2" in { } multiclass SInstMinMaxByVector { - def NAME # _SINGLE_X2 : SInst<"sv" # name # "nm[_single_{d}_x2]", "22d", "hfd", MergeNone, "aarch64_sve_f" # name # "nm_single_x2", [IsStreaming], []>; - def NAME # _SINGLE_X4 : SInst<"sv" # name # "nm[_single_{d}_x4]", "44d", "hfd", MergeNone, "aarch64_sve_f" # name # "nm_single_x4", [IsStreaming], []>; + def NAME # _SINGLE_X2 : SInst<"sv" # name # "nm[_single_{d}_x2]", "22d", "bhfd", MergeNone, "aarch64_sve_f" # name # "nm_single_x2", [IsStreaming], []>; + def NAME # _SINGLE_X4 : SInst<"sv" # name # "nm[_single_{d}_x4]", "44d", "bhfd", MergeNone, "aarch64_sve_f" # name # "nm_single_x4", [IsStreaming], []>; - def NAME # _X2 : SInst<"sv" # name # "nm[_{d}_x2]", "222", "hfd", MergeNone, "aarch64_sve_f" # name # "nm_x2", [IsStreaming], []>; - def NAME # _X4 : SInst<"sv" # name # "nm[_{d}_x4]", "444", "hfd", MergeNone, "aarch64_sve_f" # name # "nm_x4", [IsStreaming], []>; + def NAME # _X2 : SInst<"sv" # name # "nm[_{d}_x2]", "222", "bhfd", MergeNone, "aarch64_sve_f" # name # "nm_x2", [IsStreaming], []>; + def NAME # _X4 : SInst<"sv" # name # "nm[_{d}_x4]", "444", "bhfd", MergeNone, "aarch64_sve_f" # name # "nm_x4", [IsStreaming], []>; } let TargetGuard = "sme2" in { diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index c54eb543d6580ed72e9c6973fd70426907af8048..7bb781667e926c1d7fbfc9dd9925d76596de496e 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -6550,6 +6550,10 @@ def flang_deprecated_no_hlfir : Flag<["-"], "flang-deprecated-no-hlfir">, Flags<[HelpHidden]>, Visibility<[FlangOption, FC1Option]>, HelpText<"Do not use HLFIR lowering (deprecated)">; +def flang_experimental_integer_overflow : Flag<["-"], "flang-experimental-integer-overflow">, + Flags<[HelpHidden]>, Visibility<[FlangOption, FC1Option]>, + HelpText<"Add nsw flag to internal operations such as do-variable increment (experimental)">; + //===----------------------------------------------------------------------===// // FLangOption + CoreOption + NoXarchOption //===----------------------------------------------------------------------===// @@ -6647,7 +6651,9 @@ def fdebug_unparse : Flag<["-"], "fdebug-unparse">, Group, DocBrief<[{Run the parser and the semantic checks. Then unparse the parse-tree and output the generated Fortran source file.}]>; def fdebug_unparse_with_symbols : Flag<["-"], "fdebug-unparse-with-symbols">, Group, - HelpText<"Unparse and stop.">; + HelpText<"Unparse with symbols and stop.">; +def fdebug_unparse_with_modules : Flag<["-"], "fdebug-unparse-with-modules">, Group, + HelpText<"Unparse with dependent modules and stop.">; def fdebug_dump_symbols : Flag<["-"], "fdebug-dump-symbols">, Group, HelpText<"Dump symbols after the semantic analysis">; def fdebug_dump_parse_tree : Flag<["-"], "fdebug-dump-parse-tree">, Group, diff --git a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h index 724b087f7aea98f577591b6a1e96a965b0de15d2..27e9167ca1ad0222cc2a3d523576b2124ad20460 100644 --- a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h +++ b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h @@ -102,6 +102,8 @@ private: const bool EmitSymbolLabelsForTesting = false; + const bool SkipSymbolsInCategoriesToExternalTypes = false; + /// The object instantiated by the last call to serializeAPIRecord. Object *CurrentSymbol = nullptr; @@ -271,10 +273,13 @@ public: SymbolGraphSerializer(const APISet &API, const APIIgnoresList &IgnoresList, bool EmitSymbolLabelsForTesting = false, - bool ForceEmitToMainModule = false) + bool ForceEmitToMainModule = false, + bool SkipSymbolsInCategoriesToExternalTypes = false) : Base(API), ForceEmitToMainModule(ForceEmitToMainModule), IgnoresList(IgnoresList), - EmitSymbolLabelsForTesting(EmitSymbolLabelsForTesting) {} + EmitSymbolLabelsForTesting(EmitSymbolLabelsForTesting), + SkipSymbolsInCategoriesToExternalTypes( + SkipSymbolsInCategoriesToExternalTypes) {} }; } // namespace extractapi diff --git a/clang/include/clang/Lex/LiteralSupport.h b/clang/include/clang/Lex/LiteralSupport.h index 2ed42d1c5f9aae9aef473d1d85c9cec885c5d1a5..705021fcfa5b11b54d85f0b8142c5b4c59a86149 100644 --- a/clang/include/clang/Lex/LiteralSupport.h +++ b/clang/include/clang/Lex/LiteralSupport.h @@ -118,12 +118,10 @@ public: /// bits of the result and return true. Otherwise, return false. bool GetIntegerValue(llvm::APInt &Val); - /// GetFloatValue - Convert this numeric literal to a floating value, using - /// the specified APFloat fltSemantics (specifying float, double, etc). - /// The optional bool isExact (passed-by-reference) has its value - /// set to true if the returned APFloat can represent the number in the - /// literal exactly, and false otherwise. - llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result); + /// Convert this numeric literal to a floating value, using the specified + /// APFloat fltSemantics (specifying float, double, etc) and rounding mode. + llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result, + llvm::RoundingMode RM); /// GetFixedPointValue - Convert this numeric literal value into a /// scaled integer that represents this value. Returns true if an overflow diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index e89b4a2c5230e7612e07ca5fea84b67537a2a001..c0850a8fa9f7f8eeb6d468a92a481b7d9cc0bdcd 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -1010,7 +1010,7 @@ private: llvm::FoldingSet ModuleMacros; /// The names of potential module macros that we've not yet processed. - llvm::SmallVector PendingModuleMacroNames; + llvm::SmallVector PendingModuleMacroNames; /// The list of module macros, for each identifier, that are not overridden by /// any other module macro. @@ -1432,7 +1432,7 @@ public: MacroDirective *MD); /// Register an exported macro for a module and identifier. - ModuleMacro *addModuleMacro(Module *Mod, const IdentifierInfo *II, + ModuleMacro *addModuleMacro(Module *Mod, IdentifierInfo *II, MacroInfo *Macro, ArrayRef Overrides, bool &IsNew); ModuleMacro *getModuleMacro(Module *Mod, const IdentifierInfo *II); diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 7a8c2bcde804eedc7ac0261b944e2f2cc5c806d4..5f04664141d29fd728a9ade3451ff5b33830114a 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -18,6 +18,7 @@ #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaCodeCompletion.h" #include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" #include "llvm/ADT/SmallVector.h" @@ -152,6 +153,9 @@ class Parser : public CodeCompletionHandler { /// Identifier for "replacement". IdentifierInfo *Ident_replacement; + /// Identifier for "environment". + IdentifierInfo *Ident_environment; + /// Identifiers used by the 'external_source_symbol' attribute. IdentifierInfo *Ident_language, *Ident_defined_in, *Ident_generated_declaration, *Ident_USR; @@ -2480,24 +2484,23 @@ private: bool trySkippingFunctionBody(); bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, - const ParsedTemplateInfo &TemplateInfo, - AccessSpecifier AS, DeclSpecContext DSC, - ParsedAttributes &Attrs); + ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, + DeclSpecContext DSC, ParsedAttributes &Attrs); DeclSpecContext getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context); - void ParseDeclarationSpecifiers( - DeclSpec &DS, - const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), - AccessSpecifier AS = AS_none, - DeclSpecContext DSC = DeclSpecContext::DSC_normal, - LateParsedAttrList *LateAttrs = nullptr) { + void + ParseDeclarationSpecifiers(DeclSpec &DS, ParsedTemplateInfo &TemplateInfo, + AccessSpecifier AS = AS_none, + DeclSpecContext DSC = DeclSpecContext::DSC_normal, + LateParsedAttrList *LateAttrs = nullptr) { return ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC, LateAttrs, getImplicitTypenameContext(DSC)); } - void ParseDeclarationSpecifiers( - DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, - DeclSpecContext DSC, LateParsedAttrList *LateAttrs, - ImplicitTypenameContext AllowImplicitTypename); + void + ParseDeclarationSpecifiers(DeclSpec &DS, ParsedTemplateInfo &TemplateInfo, + AccessSpecifier AS, DeclSpecContext DSC, + LateParsedAttrList *LateAttrs, + ImplicitTypenameContext AllowImplicitTypename); SourceLocation ParsePackIndexingType(DeclSpec &DS); void AnnotateExistingIndexedTypeNamePack(ParsedType T, @@ -2998,7 +3001,8 @@ private: IdentifierInfo *TryParseCXX11AttributeIdentifier( SourceLocation &Loc, - Sema::AttributeCompletion Completion = Sema::AttributeCompletion::None, + SemaCodeCompletion::AttributeCompletion Completion = + SemaCodeCompletion::AttributeCompletion::None, const IdentifierInfo *EnclosingScope = nullptr); void MaybeParseHLSLAnnotations(Declarator &D, @@ -3308,7 +3312,7 @@ private: // C++ 9: classes [class] and C structs/unions. bool isValidAfterTypeSpecifier(bool CouldBeBitfield); void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc, - DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, + DeclSpec &DS, ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, bool EnteringContext, DeclSpecContext DSC, ParsedAttributes &Attributes); void SkipCXXMemberSpecification(SourceLocation StartLoc, @@ -3330,7 +3334,7 @@ private: VirtSpecifiers &VS); DeclGroupPtrTy ParseCXXClassMemberDeclaration( AccessSpecifier AS, ParsedAttributes &Attr, - const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), + ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject *DiagsFromTParams = nullptr); DeclGroupPtrTy ParseCXXClassMemberDeclarationWithPragmas(AccessSpecifier &AS, diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h index 8368d9ce61466de8d91bea09956befdd641dc14a..22cbd0d90ee432a1e52e0f24620397204c368b23 100644 --- a/clang/include/clang/Sema/ParsedAttr.h +++ b/clang/include/clang/Sema/ParsedAttr.h @@ -40,6 +40,7 @@ class LangOptions; class Sema; class Stmt; class TargetInfo; +struct IdentifierLoc; /// Represents information about a change in availability for /// an entity, which is part of the encoding of the 'availability' @@ -68,12 +69,14 @@ struct AvailabilityData { AvailabilityChange Changes[NumAvailabilitySlots]; SourceLocation StrictLoc; const Expr *Replacement; + const IdentifierLoc *EnvironmentLoc; AvailabilityData(const AvailabilityChange &Introduced, const AvailabilityChange &Deprecated, - const AvailabilityChange &Obsoleted, - SourceLocation Strict, const Expr *ReplaceExpr) - : StrictLoc(Strict), Replacement(ReplaceExpr) { + const AvailabilityChange &Obsoleted, SourceLocation Strict, + const Expr *ReplaceExpr, const IdentifierLoc *EnvironmentLoc) + : StrictLoc(Strict), Replacement(ReplaceExpr), + EnvironmentLoc(EnvironmentLoc) { Changes[IntroducedSlot] = Introduced; Changes[DeprecatedSlot] = Deprecated; Changes[ObsoletedSlot] = Obsoleted; @@ -234,7 +237,7 @@ private: const AvailabilityChange &deprecated, const AvailabilityChange &obsoleted, SourceLocation unavailable, const Expr *messageExpr, Form formUsed, SourceLocation strict, - const Expr *replacementExpr) + const Expr *replacementExpr, const IdentifierLoc *environmentLoc) : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed), NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), @@ -243,8 +246,9 @@ private: Info(ParsedAttrInfo::get(*this)) { ArgsUnion PVal(Parm); memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); - new (getAvailabilityData()) detail::AvailabilityData( - introduced, deprecated, obsoleted, strict, replacementExpr); + new (getAvailabilityData()) + detail::AvailabilityData(introduced, deprecated, obsoleted, strict, + replacementExpr, environmentLoc); } /// Constructor for objc_bridge_related attributes. @@ -445,6 +449,12 @@ public: return getAvailabilityData()->Replacement; } + const IdentifierLoc *getEnvironment() const { + assert(getParsedKind() == AT_Availability && + "Not an availability attribute"); + return getAvailabilityData()->EnvironmentLoc; + } + const ParsedType &getMatchingCType() const { assert(getParsedKind() == AT_TypeTagForDatatype && "Not a type_tag_for_datatype attribute"); @@ -759,11 +769,13 @@ public: const AvailabilityChange &obsoleted, SourceLocation unavailable, const Expr *MessageExpr, ParsedAttr::Form form, SourceLocation strict, - const Expr *ReplacementExpr) { + const Expr *ReplacementExpr, + IdentifierLoc *EnvironmentLoc) { void *memory = allocate(AttributeFactory::AvailabilityAllocSize); - return add(new (memory) ParsedAttr( - attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, - obsoleted, unavailable, MessageExpr, form, strict, ReplacementExpr)); + return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, + Param, introduced, deprecated, obsoleted, + unavailable, MessageExpr, form, strict, + ReplacementExpr, EnvironmentLoc)); } ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, @@ -994,10 +1006,12 @@ public: const AvailabilityChange &obsoleted, SourceLocation unavailable, const Expr *MessageExpr, ParsedAttr::Form form, SourceLocation strict, - const Expr *ReplacementExpr) { - ParsedAttr *attr = pool.create( - attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, - obsoleted, unavailable, MessageExpr, form, strict, ReplacementExpr); + const Expr *ReplacementExpr, + IdentifierLoc *EnvironmentLoc) { + ParsedAttr *attr = + pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced, + deprecated, obsoleted, unavailable, MessageExpr, form, + strict, ReplacementExpr, EnvironmentLoc); addAtEnd(attr); return attr; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6a414aa57f32bea3ea8f1b798cddb27d0a8ebf9d..6c89d275215de35815ae1bdc35042003b24583f4 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -39,6 +39,7 @@ #include "clang/Basic/Cuda.h" #include "clang/Basic/DarwinSDKInfo.h" #include "clang/Basic/ExpressionTraits.h" +#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Module.h" #include "clang/Basic/OpenCLOptions.h" #include "clang/Basic/PragmaKinds.h" @@ -167,6 +168,7 @@ class Preprocessor; class PseudoDestructorTypeStorage; class PseudoObjectExpr; class QualType; +class SemaCodeCompletion; class SemaCUDA; class SemaHLSL; class SemaObjC; @@ -481,9 +483,8 @@ class Sema final : public SemaBase { // 29. C++ Variadic Templates (SemaTemplateVariadic.cpp) // 30. Constraints and Concepts (SemaConcept.cpp) // 31. Types (SemaType.cpp) - // 32. Code Completion (SemaCodeComplete.cpp) - // 33. FixIt Helpers (SemaFixItUtils.cpp) - // 34. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) + // 32. FixIt Helpers (SemaFixItUtils.cpp) + // 33. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) /// \name Semantic Analysis /// Implementations are in Sema.cpp @@ -984,6 +985,11 @@ public: /// CurContext - This is the current declaration context of parsing. DeclContext *CurContext; + SemaCodeCompletion &CodeCompletion() { + assert(CodeCompletionPtr); + return *CodeCompletionPtr; + } + SemaCUDA &CUDA() { assert(CUDAPtr); return *CUDAPtr; @@ -1044,6 +1050,7 @@ private: mutable IdentifierInfo *Ident_super; + std::unique_ptr CodeCompletionPtr; std::unique_ptr CUDAPtr; std::unique_ptr HLSLPtr; std::unique_ptr ObjCPtr; @@ -2022,6 +2029,8 @@ public: void CheckTCBEnforcement(const SourceLocation CallExprLoc, const NamedDecl *Callee); + void CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc); + private: void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, const ArraySubscriptExpr *ASE = nullptr, @@ -3301,7 +3310,7 @@ public: /// Subroutines of ActOnDeclarator(). TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T, TypeSourceInfo *TInfo); - bool isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New); + bool isIncompatibleTypedef(const TypeDecl *Old, TypedefNameDecl *New); /// Describes the kind of merge to perform for availability /// attributes (including "deprecated", "unavailable", and "availability"). @@ -3572,13 +3581,13 @@ public: bool CheckAttrTarget(const ParsedAttr &CurrAttr); bool CheckAttrNoArgs(const ParsedAttr &CurrAttr); - AvailabilityAttr * - mergeAvailabilityAttr(NamedDecl *D, const AttributeCommonInfo &CI, - IdentifierInfo *Platform, bool Implicit, - VersionTuple Introduced, VersionTuple Deprecated, - VersionTuple Obsoleted, bool IsUnavailable, - StringRef Message, bool IsStrict, StringRef Replacement, - AvailabilityMergeKind AMK, int Priority); + AvailabilityAttr *mergeAvailabilityAttr( + NamedDecl *D, const AttributeCommonInfo &CI, IdentifierInfo *Platform, + bool Implicit, VersionTuple Introduced, VersionTuple Deprecated, + VersionTuple Obsoleted, bool IsUnavailable, StringRef Message, + bool IsStrict, StringRef Replacement, AvailabilityMergeKind AMK, + int Priority, IdentifierInfo *IIEnvironment); + TypeVisibilityAttr * mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI, TypeVisibilityAttr::VisibilityType Vis); @@ -4799,6 +4808,11 @@ public: DelayedDiagnostics.popUndelayed(state); } + ValueDecl *tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl, + CXXScopeSpec &SS, + ParsedType TemplateTypeTy, + IdentifierInfo *MemberOrBase); + private: void setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem, QualType ResultTy, @@ -4809,11 +4823,6 @@ private: // of a ComparisonCategoryType enumerator. llvm::SmallBitVector FullyCheckedComparisonCategories; - ValueDecl *tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl, - CXXScopeSpec &SS, - ParsedType TemplateTypeTy, - IdentifierInfo *MemberOrBase); - /// Check if there is a field shadowing. void CheckShadowInheritedFields(const SourceLocation &Loc, DeclarationName FieldName, @@ -9133,7 +9142,7 @@ public: CheckTemplateArgumentKind CTAK); bool CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, TemplateParameterList *Params, - TemplateArgumentLoc &Arg); + TemplateArgumentLoc &Arg, bool IsDeduced); void NoteTemplateLocation(const NamedDecl &Decl, std::optional ParamRange = {}); @@ -9356,7 +9365,8 @@ public: Decl *ActOnConceptDefinition(Scope *S, MultiTemplateParamsArg TemplateParameterLists, const IdentifierInfo *Name, - SourceLocation NameLoc, Expr *ConstraintExpr); + SourceLocation NameLoc, Expr *ConstraintExpr, + const ParsedAttributesView &Attrs); void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous, bool &AddToScope); @@ -9492,6 +9502,15 @@ public: ArrayRef TemplateArgs, sema::TemplateDeductionInfo &Info); + /// Deduce the template arguments of the given template from \p FromType. + /// Used to implement the IsDeducible constraint for alias CTAD per C++ + /// [over.match.class.deduct]p4. + /// + /// It only supports class or type alias templates. + TemplateDeductionResult + DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType, + sema::TemplateDeductionInfo &Info); + TemplateDeductionResult DeduceTemplateArguments( TemplateParameterList *TemplateParams, ArrayRef Ps, ArrayRef As, sema::TemplateDeductionInfo &Info, @@ -9603,7 +9622,8 @@ public: sema::TemplateDeductionInfo &Info); bool isTemplateTemplateParameterAtLeastAsSpecializedAs( - TemplateParameterList *PParam, TemplateDecl *AArg, SourceLocation Loc); + TemplateParameterList *PParam, TemplateDecl *AArg, SourceLocation Loc, + bool IsDeduced); void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, unsigned Depth, llvm::SmallBitVector &Used); @@ -11651,209 +11671,6 @@ private: // // - /// \name Code Completion - /// Implementations are in SemaCodeComplete.cpp - ///@{ - -public: - /// Code-completion consumer. - CodeCompleteConsumer *CodeCompleter; - - /// Describes the context in which code completion occurs. - enum ParserCompletionContext { - /// Code completion occurs at top-level or namespace context. - PCC_Namespace, - /// Code completion occurs within a class, struct, or union. - PCC_Class, - /// Code completion occurs within an Objective-C interface, protocol, - /// or category. - PCC_ObjCInterface, - /// Code completion occurs within an Objective-C implementation or - /// category implementation - PCC_ObjCImplementation, - /// Code completion occurs within the list of instance variables - /// in an Objective-C interface, protocol, category, or implementation. - PCC_ObjCInstanceVariableList, - /// Code completion occurs following one or more template - /// headers. - PCC_Template, - /// Code completion occurs following one or more template - /// headers within a class. - PCC_MemberTemplate, - /// Code completion occurs within an expression. - PCC_Expression, - /// Code completion occurs within a statement, which may - /// also be an expression or a declaration. - PCC_Statement, - /// Code completion occurs at the beginning of the - /// initialization statement (or expression) in a for loop. - PCC_ForInit, - /// Code completion occurs within the condition of an if, - /// while, switch, or for statement. - PCC_Condition, - /// Code completion occurs within the body of a function on a - /// recovery path, where we do not have a specific handle on our position - /// in the grammar. - PCC_RecoveryInFunction, - /// Code completion occurs where only a type is permitted. - PCC_Type, - /// Code completion occurs in a parenthesized expression, which - /// might also be a type cast. - PCC_ParenthesizedExpression, - /// Code completion occurs within a sequence of declaration - /// specifiers within a function, method, or block. - PCC_LocalDeclarationSpecifiers, - /// Code completion occurs at top-level in a REPL session - PCC_TopLevelOrExpression, - }; - - void CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path); - void CodeCompleteOrdinaryName(Scope *S, - ParserCompletionContext CompletionContext); - void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, bool AllowNonIdentifiers, - bool AllowNestedNameSpecifiers); - - struct CodeCompleteExpressionData; - void CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data); - void CodeCompleteExpression(Scope *S, QualType PreferredType, - bool IsParenthesized = false); - void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, Expr *OtherOpBase, - SourceLocation OpLoc, bool IsArrow, - bool IsBaseExprStatement, - QualType PreferredType); - void CodeCompletePostfixExpression(Scope *S, ExprResult LHS, - QualType PreferredType); - void CodeCompleteTag(Scope *S, unsigned TagSpec); - void CodeCompleteTypeQualifiers(DeclSpec &DS); - void CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D, - const VirtSpecifiers *VS = nullptr); - void CodeCompleteBracketDeclarator(Scope *S); - void CodeCompleteCase(Scope *S); - enum class AttributeCompletion { - Attribute, - Scope, - None, - }; - void CodeCompleteAttribute( - AttributeCommonInfo::Syntax Syntax, - AttributeCompletion Completion = AttributeCompletion::Attribute, - const IdentifierInfo *Scope = nullptr); - /// Determines the preferred type of the current function argument, by - /// examining the signatures of all possible overloads. - /// Returns null if unknown or ambiguous, or if code completion is off. - /// - /// If the code completion point has been reached, also reports the function - /// signatures that were considered. - /// - /// FIXME: rename to GuessCallArgumentType to reduce confusion. - QualType ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args, - SourceLocation OpenParLoc); - QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc, - ArrayRef Args, - SourceLocation OpenParLoc, - bool Braced); - QualType ProduceCtorInitMemberSignatureHelp( - Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy, - ArrayRef ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc, - bool Braced); - QualType ProduceTemplateArgumentSignatureHelp( - TemplateTy, ArrayRef, SourceLocation LAngleLoc); - void CodeCompleteInitializer(Scope *S, Decl *D); - /// Trigger code completion for a record of \p BaseType. \p InitExprs are - /// expressions in the initializer list seen so far and \p D is the current - /// Designation being parsed. - void CodeCompleteDesignator(const QualType BaseType, - llvm::ArrayRef InitExprs, - const Designation &D); - void CodeCompleteAfterIf(Scope *S, bool IsBracedThen); - - void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext, - bool IsUsingDeclaration, QualType BaseType, - QualType PreferredType); - void CodeCompleteUsing(Scope *S); - void CodeCompleteUsingDirective(Scope *S); - void CodeCompleteNamespaceDecl(Scope *S); - void CodeCompleteNamespaceAliasDecl(Scope *S); - void CodeCompleteOperatorName(Scope *S); - void CodeCompleteConstructorInitializer( - Decl *Constructor, ArrayRef Initializers); - - void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, - bool AfterAmpersand); - void CodeCompleteAfterFunctionEquals(Declarator &D); - - void CodeCompleteObjCAtDirective(Scope *S); - void CodeCompleteObjCAtVisibility(Scope *S); - void CodeCompleteObjCAtStatement(Scope *S); - void CodeCompleteObjCAtExpression(Scope *S); - void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS); - void CodeCompleteObjCPropertyGetter(Scope *S); - void CodeCompleteObjCPropertySetter(Scope *S); - void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, - bool IsParameter); - void CodeCompleteObjCMessageReceiver(Scope *S); - void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, - ArrayRef SelIdents, - bool AtArgumentExpression); - void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, - ArrayRef SelIdents, - bool AtArgumentExpression, - bool IsSuper = false); - void CodeCompleteObjCInstanceMessage( - Scope *S, Expr *Receiver, ArrayRef SelIdents, - bool AtArgumentExpression, ObjCInterfaceDecl *Super = nullptr); - void CodeCompleteObjCForCollection(Scope *S, DeclGroupPtrTy IterationVar); - void CodeCompleteObjCSelector(Scope *S, - ArrayRef SelIdents); - void - CodeCompleteObjCProtocolReferences(ArrayRef Protocols); - void CodeCompleteObjCProtocolDecl(Scope *S); - void CodeCompleteObjCInterfaceDecl(Scope *S); - void CodeCompleteObjCClassForwardDecl(Scope *S); - void CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, - SourceLocation ClassNameLoc); - void CodeCompleteObjCImplementationDecl(Scope *S); - void CodeCompleteObjCInterfaceCategory(Scope *S, IdentifierInfo *ClassName, - SourceLocation ClassNameLoc); - void CodeCompleteObjCImplementationCategory(Scope *S, - IdentifierInfo *ClassName, - SourceLocation ClassNameLoc); - void CodeCompleteObjCPropertyDefinition(Scope *S); - void CodeCompleteObjCPropertySynthesizeIvar(Scope *S, - IdentifierInfo *PropertyName); - void CodeCompleteObjCMethodDecl(Scope *S, - std::optional IsInstanceMethod, - ParsedType ReturnType); - void CodeCompleteObjCMethodDeclSelector( - Scope *S, bool IsInstanceMethod, bool AtParameterName, - ParsedType ReturnType, ArrayRef SelIdents); - void CodeCompleteObjCClassPropertyRefExpr(Scope *S, - const IdentifierInfo &ClassName, - SourceLocation ClassNameLoc, - bool IsBaseExprStatement); - void CodeCompletePreprocessorDirective(bool InConditional); - void CodeCompleteInPreprocessorConditionalExclusion(Scope *S); - void CodeCompletePreprocessorMacroName(bool IsDefinition); - void CodeCompletePreprocessorExpression(); - void CodeCompletePreprocessorMacroArgument(Scope *S, IdentifierInfo *Macro, - MacroInfo *MacroInfo, - unsigned Argument); - void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled); - void CodeCompleteNaturalLanguage(); - void CodeCompleteAvailabilityPlatformName(); - void - GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo, - SmallVectorImpl &Results); - - ///@} - - // - // - // ------------------------------------------------------------------------- - // - // - /// \name FixIt Helpers /// Implementations are in SemaFixItUtils.cpp ///@{ diff --git a/clang/include/clang/Sema/SemaCodeCompletion.h b/clang/include/clang/Sema/SemaCodeCompletion.h new file mode 100644 index 0000000000000000000000000000000000000000..6bf0f2473cbf437f146ca585a9302c95d2a350d2 --- /dev/null +++ b/clang/include/clang/Sema/SemaCodeCompletion.h @@ -0,0 +1,237 @@ +//===----- SemaCodeCompletion.h ------ Code completion support ------------===// +// +// 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 facilities that support code completion. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_SEMACODECOMPLETION_H +#define LLVM_CLANG_SEMA_SEMACODECOMPLETION_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Type.h" +#include "clang/Basic/AttributeCommonInfo.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/MacroInfo.h" +#include "clang/Lex/ModuleLoader.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Designator.h" +#include "clang/Sema/Ownership.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/SemaBase.h" +#include "llvm/ADT/StringRef.h" +#include + +namespace clang { + +class SemaCodeCompletion : public SemaBase { +public: + SemaCodeCompletion(Sema &S, CodeCompleteConsumer *CompletionConsumer); + + using TemplateTy = OpaquePtr; + using DeclGroupPtrTy = OpaquePtr; + + /// Code-completion consumer. + CodeCompleteConsumer *CodeCompleter; + + /// Describes the context in which code completion occurs. + enum ParserCompletionContext { + /// Code completion occurs at top-level or namespace context. + PCC_Namespace, + /// Code completion occurs within a class, struct, or union. + PCC_Class, + /// Code completion occurs within an Objective-C interface, protocol, + /// or category. + PCC_ObjCInterface, + /// Code completion occurs within an Objective-C implementation or + /// category implementation + PCC_ObjCImplementation, + /// Code completion occurs within the list of instance variables + /// in an Objective-C interface, protocol, category, or implementation. + PCC_ObjCInstanceVariableList, + /// Code completion occurs following one or more template + /// headers. + PCC_Template, + /// Code completion occurs following one or more template + /// headers within a class. + PCC_MemberTemplate, + /// Code completion occurs within an expression. + PCC_Expression, + /// Code completion occurs within a statement, which may + /// also be an expression or a declaration. + PCC_Statement, + /// Code completion occurs at the beginning of the + /// initialization statement (or expression) in a for loop. + PCC_ForInit, + /// Code completion occurs within the condition of an if, + /// while, switch, or for statement. + PCC_Condition, + /// Code completion occurs within the body of a function on a + /// recovery path, where we do not have a specific handle on our position + /// in the grammar. + PCC_RecoveryInFunction, + /// Code completion occurs where only a type is permitted. + PCC_Type, + /// Code completion occurs in a parenthesized expression, which + /// might also be a type cast. + PCC_ParenthesizedExpression, + /// Code completion occurs within a sequence of declaration + /// specifiers within a function, method, or block. + PCC_LocalDeclarationSpecifiers, + /// Code completion occurs at top-level in a REPL session + PCC_TopLevelOrExpression, + }; + + void CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path); + void CodeCompleteOrdinaryName(Scope *S, + ParserCompletionContext CompletionContext); + void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, bool AllowNonIdentifiers, + bool AllowNestedNameSpecifiers); + + struct CodeCompleteExpressionData; + void CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data); + void CodeCompleteExpression(Scope *S, QualType PreferredType, + bool IsParenthesized = false); + void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, Expr *OtherOpBase, + SourceLocation OpLoc, bool IsArrow, + bool IsBaseExprStatement, + QualType PreferredType); + void CodeCompletePostfixExpression(Scope *S, ExprResult LHS, + QualType PreferredType); + void CodeCompleteTag(Scope *S, unsigned TagSpec); + void CodeCompleteTypeQualifiers(DeclSpec &DS); + void CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D, + const VirtSpecifiers *VS = nullptr); + void CodeCompleteBracketDeclarator(Scope *S); + void CodeCompleteCase(Scope *S); + enum class AttributeCompletion { + Attribute, + Scope, + None, + }; + void CodeCompleteAttribute( + AttributeCommonInfo::Syntax Syntax, + AttributeCompletion Completion = AttributeCompletion::Attribute, + const IdentifierInfo *Scope = nullptr); + /// Determines the preferred type of the current function argument, by + /// examining the signatures of all possible overloads. + /// Returns null if unknown or ambiguous, or if code completion is off. + /// + /// If the code completion point has been reached, also reports the function + /// signatures that were considered. + /// + /// FIXME: rename to GuessCallArgumentType to reduce confusion. + QualType ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args, + SourceLocation OpenParLoc); + QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc, + ArrayRef Args, + SourceLocation OpenParLoc, + bool Braced); + QualType ProduceCtorInitMemberSignatureHelp( + Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy, + ArrayRef ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc, + bool Braced); + QualType ProduceTemplateArgumentSignatureHelp( + TemplateTy, ArrayRef, SourceLocation LAngleLoc); + void CodeCompleteInitializer(Scope *S, Decl *D); + /// Trigger code completion for a record of \p BaseType. \p InitExprs are + /// expressions in the initializer list seen so far and \p D is the current + /// Designation being parsed. + void CodeCompleteDesignator(const QualType BaseType, + llvm::ArrayRef InitExprs, + const Designation &D); + void CodeCompleteAfterIf(Scope *S, bool IsBracedThen); + + void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext, + bool IsUsingDeclaration, QualType BaseType, + QualType PreferredType); + void CodeCompleteUsing(Scope *S); + void CodeCompleteUsingDirective(Scope *S); + void CodeCompleteNamespaceDecl(Scope *S); + void CodeCompleteNamespaceAliasDecl(Scope *S); + void CodeCompleteOperatorName(Scope *S); + void CodeCompleteConstructorInitializer( + Decl *Constructor, ArrayRef Initializers); + + void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, + bool AfterAmpersand); + void CodeCompleteAfterFunctionEquals(Declarator &D); + + void CodeCompleteObjCAtDirective(Scope *S); + void CodeCompleteObjCAtVisibility(Scope *S); + void CodeCompleteObjCAtStatement(Scope *S); + void CodeCompleteObjCAtExpression(Scope *S); + void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS); + void CodeCompleteObjCPropertyGetter(Scope *S); + void CodeCompleteObjCPropertySetter(Scope *S); + void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, + bool IsParameter); + void CodeCompleteObjCMessageReceiver(Scope *S); + void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, + ArrayRef SelIdents, + bool AtArgumentExpression); + void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, + ArrayRef SelIdents, + bool AtArgumentExpression, + bool IsSuper = false); + void CodeCompleteObjCInstanceMessage( + Scope *S, Expr *Receiver, ArrayRef SelIdents, + bool AtArgumentExpression, ObjCInterfaceDecl *Super = nullptr); + void CodeCompleteObjCForCollection(Scope *S, DeclGroupPtrTy IterationVar); + void CodeCompleteObjCSelector(Scope *S, + ArrayRef SelIdents); + void + CodeCompleteObjCProtocolReferences(ArrayRef Protocols); + void CodeCompleteObjCProtocolDecl(Scope *S); + void CodeCompleteObjCInterfaceDecl(Scope *S); + void CodeCompleteObjCClassForwardDecl(Scope *S); + void CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, + SourceLocation ClassNameLoc); + void CodeCompleteObjCImplementationDecl(Scope *S); + void CodeCompleteObjCInterfaceCategory(Scope *S, IdentifierInfo *ClassName, + SourceLocation ClassNameLoc); + void CodeCompleteObjCImplementationCategory(Scope *S, + IdentifierInfo *ClassName, + SourceLocation ClassNameLoc); + void CodeCompleteObjCPropertyDefinition(Scope *S); + void CodeCompleteObjCPropertySynthesizeIvar(Scope *S, + IdentifierInfo *PropertyName); + void CodeCompleteObjCMethodDecl(Scope *S, + std::optional IsInstanceMethod, + ParsedType ReturnType); + void CodeCompleteObjCMethodDeclSelector( + Scope *S, bool IsInstanceMethod, bool AtParameterName, + ParsedType ReturnType, ArrayRef SelIdents); + void CodeCompleteObjCClassPropertyRefExpr(Scope *S, + const IdentifierInfo &ClassName, + SourceLocation ClassNameLoc, + bool IsBaseExprStatement); + void CodeCompletePreprocessorDirective(bool InConditional); + void CodeCompleteInPreprocessorConditionalExclusion(Scope *S); + void CodeCompletePreprocessorMacroName(bool IsDefinition); + void CodeCompletePreprocessorExpression(); + void CodeCompletePreprocessorMacroArgument(Scope *S, IdentifierInfo *Macro, + MacroInfo *MacroInfo, + unsigned Argument); + void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled); + void CodeCompleteNaturalLanguage(); + void CodeCompleteAvailabilityPlatformName(); + void + GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo, + SmallVectorImpl &Results); +}; + +} // namespace clang + +#endif // LLVM_CLANG_SEMA_SEMACODECOMPLETION_H diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 7bb0e81545bd151e9c6ba2abda627760e51b5124..88192e439a3f05cc72b4b14dc2def72a8b1da679 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -565,7 +565,8 @@ private: void GenerateNameLookupTable(const DeclContext *DC, llvm::SmallVectorImpl &LookupTable); - uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC); + uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, + const DeclContext *DC); uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC); void WriteTypeDeclOffsets(); void WriteFileDeclIDsMap(); @@ -714,9 +715,6 @@ public: /// Force a type to be emitted and get its ID. serialization::TypeID GetOrCreateTypeID(QualType T); - /// Determine the type ID of an already-emitted type. - serialization::TypeID getTypeID(QualType T) const; - /// Find the first local declaration of a given local redeclarable /// decl. const Decl *getFirstLocalDecl(const Decl *D); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h index ccfe8d47c290bcaa294ecf797a3e52c01b45afbd..a99c11766f1105e8c816461455a14c7ad4e09083 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h @@ -56,9 +56,10 @@ public: /// overloaded operator, a constructor or a destructor). CXXMethod, - /// Match any CallEvent that is not an ObjCMethodCall. - /// FIXME: Previously this was the default behavior of CallDescription, but - /// its use should be replaced by a more specific mode almost everywhere. + /// Match any CallEvent that is not an ObjCMethodCall. This should not be + /// used when the checker looks for a concrete function (and knows whether + /// it is a method); but GenericTaintChecker uses this mode to match + /// functions whose name was configured by the user. Unspecified, /// FIXME: Add support for ObjCMethodCall events (I'm not adding it because @@ -100,13 +101,6 @@ public: MaybeCount RequiredArgs = std::nullopt, MaybeCount RequiredParams = std::nullopt); - /// Construct a CallDescription with default flags. - CallDescription(ArrayRef QualifiedName, - MaybeCount RequiredArgs = std::nullopt, - MaybeCount RequiredParams = std::nullopt); - - CallDescription(std::nullptr_t) = delete; - /// Get the name of the function that this object matches. StringRef getFunctionName() const { return QualifiedName.back(); } diff --git a/clang/include/clang/Tooling/NodeIntrospection.h b/clang/include/clang/Tooling/NodeIntrospection.h deleted file mode 100644 index 91552cad2eca388f0616ef3f909d3f27fb20ef53..0000000000000000000000000000000000000000 --- a/clang/include/clang/Tooling/NodeIntrospection.h +++ /dev/null @@ -1,101 +0,0 @@ -//===- NodeIntrospection.h ------------------------------------*- C++ -*---===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the implementation of the NodeIntrospection. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLING_NODEINTROSPECTION_H -#define LLVM_CLANG_TOOLING_NODEINTROSPECTION_H - -#include "clang/AST/ASTTypeTraits.h" -#include "clang/AST/DeclarationName.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" -#include - -namespace clang { - -class Stmt; -class Decl; -class CXXCtorInitializer; -class NestedNameSpecifierLoc; -class TemplateArgumentLoc; -class CXXBaseSpecifier; -struct DeclarationNameInfo; - -namespace tooling { - -class LocationCall; -using SharedLocationCall = llvm::IntrusiveRefCntPtr; - -class LocationCall : public llvm::ThreadSafeRefCountedBase { -public: - enum LocationCallFlags { NoFlags, ReturnsPointer, IsCast }; - LocationCall(SharedLocationCall on, std::string name, - LocationCallFlags flags = NoFlags) - : m_flags(flags), m_on(std::move(on)), m_name(std::move(name)) {} - - LocationCall *on() const { return m_on.get(); } - StringRef name() const { return m_name; } - bool returnsPointer() const { return m_flags & ReturnsPointer; } - bool isCast() const { return m_flags & IsCast; } - -private: - LocationCallFlags m_flags; - SharedLocationCall m_on; - std::string m_name; -}; - -class LocationCallFormatterCpp { -public: - static void print(const LocationCall &Call, llvm::raw_ostream &OS); - static std::string format(const LocationCall &Call); -}; - -namespace internal { -struct RangeLessThan { - bool operator()(std::pair const &LHS, - std::pair const &RHS) const; - bool - operator()(std::pair const &LHS, - std::pair const &RHS) const; -}; - -} // namespace internal - -// Note that this container stores unique results in a deterministic, but -// the location calls are in an unspecified order. Clients which desire -// a particular order for the location calls, such as alphabetical, -// should sort results after retrieval, because the order is dependent -// on how the LocationCalls are formatted. -template -using UniqueMultiMap = std::set, internal::RangeLessThan>; - -using SourceLocationMap = UniqueMultiMap; -using SourceRangeMap = UniqueMultiMap; - -struct NodeLocationAccessors { - SourceLocationMap LocationAccessors; - SourceRangeMap RangeAccessors; -}; - -namespace NodeIntrospection { -bool hasIntrospectionSupport(); -NodeLocationAccessors GetLocations(clang::Stmt const *Object); -NodeLocationAccessors GetLocations(clang::Decl const *Object); -NodeLocationAccessors GetLocations(clang::CXXCtorInitializer const *Object); -NodeLocationAccessors GetLocations(clang::NestedNameSpecifierLoc const &); -NodeLocationAccessors GetLocations(clang::TemplateArgumentLoc const &); -NodeLocationAccessors GetLocations(clang::CXXBaseSpecifier const *); -NodeLocationAccessors GetLocations(clang::TypeLoc const &); -NodeLocationAccessors GetLocations(clang::DeclarationNameInfo const &); -NodeLocationAccessors GetLocations(clang::DynTypedNode const &Node); -} // namespace NodeIntrospection -} // namespace tooling -} // namespace clang -#endif diff --git a/clang/lib/ARCMigrate/ARCMT.cpp b/clang/lib/ARCMigrate/ARCMT.cpp index b410d5f3b42a7eae63a838ee842637c376df02ba..5835559bff6b720842e6a419c3910f17891aa111 100644 --- a/clang/lib/ARCMigrate/ARCMT.cpp +++ b/clang/lib/ARCMigrate/ARCMT.cpp @@ -606,8 +606,7 @@ bool MigrationProcess::applyTransform(TransformFn trans, llvm::raw_svector_ostream vecOS(newText); buf.write(vecOS); std::unique_ptr memBuf( - llvm::MemoryBuffer::getMemBufferCopy( - StringRef(newText.data(), newText.size()), newFname)); + llvm::MemoryBuffer::getMemBufferCopy(newText.str(), newFname)); SmallString<64> filePath(file->getName()); Unit->getFileManager().FixupRelativePath(filePath); Remapper.remap(filePath.str(), std::move(memBuf)); diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp index aaf41dc4039cd7f8d735501723908d9ca67c6be0..4357c8e3f09a55080ceb9ee389b7df11f6691b33 100644 --- a/clang/lib/ARCMigrate/ObjCMT.cpp +++ b/clang/lib/ARCMigrate/ObjCMT.cpp @@ -1963,8 +1963,7 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) { llvm::raw_svector_ostream vecOS(newText); buf.write(vecOS); std::unique_ptr memBuf( - llvm::MemoryBuffer::getMemBufferCopy( - StringRef(newText.data(), newText.size()), file->getName())); + llvm::MemoryBuffer::getMemBufferCopy(newText.str(), file->getName())); SmallString<64> filePath(file->getName()); FileMgr.FixupRelativePath(filePath); Remapper.remap(filePath.str(), std::move(memBuf)); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 4475f399a120b2e055add544d693188694393cd1..8fc2bb8c401c2f4c1ea8482f1a333e6f273f241c 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5910,7 +5910,8 @@ QualType ASTContext::getUnconstrainedType(QualType T) const { if (auto *AT = CanonT->getAs()) { if (!AT->isConstrained()) return T; - return getQualifiedType(getAutoType(QualType(), AT->getKeyword(), false, + return getQualifiedType(getAutoType(QualType(), AT->getKeyword(), + AT->isDependentType(), AT->containsUnexpandedParameterPack()), T.getQualifiers()); } diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index ec851c9371e10af401b740a156ec669379ce384c..41fbfe281ef65b3a82e46e8b0cd622fe0b7d4914 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4199,14 +4199,12 @@ FunctionDecl::getTemplateSpecializationArgsAsWritten() const { return nullptr; } -void -FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C, - FunctionTemplateDecl *Template, - const TemplateArgumentList *TemplateArgs, - void *InsertPos, - TemplateSpecializationKind TSK, - const TemplateArgumentListInfo *TemplateArgsAsWritten, - SourceLocation PointOfInstantiation) { +void FunctionDecl::setFunctionTemplateSpecialization( + ASTContext &C, FunctionTemplateDecl *Template, + TemplateArgumentList *TemplateArgs, void *InsertPos, + TemplateSpecializationKind TSK, + const TemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation PointOfInstantiation) { assert((TemplateOrSpecialization.isNull() || TemplateOrSpecialization.is()) && "Member function is already a specialization"); diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 03e1055251c24f446d502b0bfb2f04d857bf92f0..65d5eeb6354eba8820b96f1377beb68cb1988074 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -666,12 +666,28 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, // Make sure that this declaration has already been introduced. if (!A->getIntroduced().empty() && EnclosingVersion < A->getIntroduced()) { - if (Message) { - Message->clear(); - llvm::raw_string_ostream Out(*Message); - VersionTuple VTI(A->getIntroduced()); - Out << "introduced in " << PrettyPlatformName << ' ' - << VTI << HintMessage; + IdentifierInfo *IIEnv = A->getEnvironment(); + StringRef TargetEnv = + Context.getTargetInfo().getTriple().getEnvironmentName(); + StringRef EnvName = AvailabilityAttr::getPrettyEnviromentName(TargetEnv); + // Matching environment or no environment on attribute + if (!IIEnv || (!TargetEnv.empty() && IIEnv->getName() == TargetEnv)) { + if (Message) { + Message->clear(); + llvm::raw_string_ostream Out(*Message); + VersionTuple VTI(A->getIntroduced()); + Out << "introduced in " << PrettyPlatformName << " " << VTI << " " + << EnvName << HintMessage; + } + } + // Non-matching environment or no environment on target + else { + if (Message) { + Message->clear(); + llvm::raw_string_ostream Out(*Message); + Out << "not available on " << PrettyPlatformName << " " << EnvName + << HintMessage; + } } return A->getStrict() ? AR_Unavailable : AR_NotYetIntroduced; diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index d22ecc3c032e7a6cdaf538200893c7672212d9b0..26765a5da1dc64b40f97ecb366462f0d8861bfab 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -884,7 +884,7 @@ TemplateArgumentList::CreateCopy(ASTContext &Context, FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create( ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template, - TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs, + TemplateSpecializationKind TSK, TemplateArgumentList *TemplateArgs, const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI, MemberSpecializationInfo *MSInfo) { const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 205e53f02b1a029c35394680ca20b0856d429691..70328c1f52af35124b5d4bdc9a41a5b3ac7e94a5 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2531,6 +2531,51 @@ bool ByteCodeExprGen::VisitConvertVectorExpr( return true; } +template +bool ByteCodeExprGen::VisitShuffleVectorExpr( + const ShuffleVectorExpr *E) { + assert(Initializing); + assert(E->getNumSubExprs() > 2); + + const Expr *Vecs[] = {E->getExpr(0), E->getExpr(1)}; + assert(Vecs[0]->getType() == Vecs[1]->getType()); + + const VectorType *VT = Vecs[0]->getType()->castAs(); + PrimType ElemT = classifyPrim(VT->getElementType()); + unsigned NumInputElems = VT->getNumElements(); + unsigned NumOutputElems = E->getNumSubExprs() - 2; + assert(NumOutputElems > 0); + + // Save both input vectors to a local variable. + unsigned VectorOffsets[2]; + for (unsigned I = 0; I != 2; ++I) { + VectorOffsets[I] = this->allocateLocalPrimitive( + Vecs[I], PT_Ptr, /*IsConst=*/true, /*IsExtended=*/false); + if (!this->visit(Vecs[I])) + return false; + if (!this->emitSetLocal(PT_Ptr, VectorOffsets[I], E)) + return false; + } + for (unsigned I = 0; I != NumOutputElems; ++I) { + APSInt ShuffleIndex = E->getShuffleMaskIdx(Ctx.getASTContext(), I); + if (ShuffleIndex == -1) + return this->emitInvalid(E); // FIXME: Better diagnostic. + + assert(ShuffleIndex < (NumInputElems * 2)); + if (!this->emitGetLocal(PT_Ptr, + VectorOffsets[ShuffleIndex >= NumInputElems], E)) + return false; + unsigned InputVectorIndex = ShuffleIndex.getZExtValue() % NumInputElems; + if (!this->emitArrayElemPop(ElemT, InputVectorIndex, E)) + return false; + + if (!this->emitInitElem(ElemT, I, E)) + return false; + } + + return true; +} + template bool ByteCodeExprGen::discard(const Expr *E) { OptionScope Scope(this, /*NewDiscardResult=*/true, /*NewInitializing=*/false); diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index fba4e45b9aa23cd70ce5b2c7ea5767e58acfb6e8..e73a2f0334cf657813c63179107f84cdf758b38b 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -124,6 +124,7 @@ public: bool VisitRecoveryExpr(const RecoveryExpr *E); bool VisitAddrLabelExpr(const AddrLabelExpr *E); bool VisitConvertVectorExpr(const ConvertVectorExpr *E); + bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E); protected: bool visitExpr(const Expr *E) override; diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index cb6c8b2ef1072be9f83e0acd7ef27bb881ac81ed..338a85525b38485201d677c3b294453d897f5fd0 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -16,17 +16,22 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/Stmt.h" #include "clang/AST/Type.h" #include "clang/Analysis/FlowSensitive/ASTOps.h" +#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" #include "clang/Analysis/FlowSensitive/DataflowLattice.h" #include "clang/Analysis/FlowSensitive/Value.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/Support/ErrorHandling.h" +#include #include +#include #include #define DEBUG_TYPE "dataflow" @@ -290,15 +295,14 @@ widenKeyToValueMap(const llvm::MapVector &CurMap, namespace { // Visitor that builds a map from record prvalues to result objects. -// This traverses the body of the function to be analyzed; for each result -// object that it encounters, it propagates the storage location of the result -// object to all record prvalues that can initialize it. +// For each result object that it encounters, it propagates the storage location +// of the result object to all record prvalues that can initialize it. class ResultObjectVisitor : public RecursiveASTVisitor { public: // `ResultObjectMap` will be filled with a map from record prvalues to result - // object. If the function being analyzed returns a record by value, - // `LocForRecordReturnVal` is the location to which this record should be - // written; otherwise, it is null. + // object. If this visitor will traverse a function that returns a record by + // value, `LocForRecordReturnVal` is the location to which this record should + // be written; otherwise, it is null. explicit ResultObjectVisitor( llvm::DenseMap &ResultObjectMap, RecordStorageLocation *LocForRecordReturnVal, @@ -514,39 +518,31 @@ private: } // namespace -Environment::Environment(DataflowAnalysisContext &DACtx) - : DACtx(&DACtx), - FlowConditionToken(DACtx.arena().makeFlowConditionToken()) {} - -Environment::Environment(DataflowAnalysisContext &DACtx, - const DeclContext &DeclCtx) - : Environment(DACtx) { - CallStack.push_back(&DeclCtx); -} - void Environment::initialize() { - const DeclContext *DeclCtx = getDeclCtx(); - if (DeclCtx == nullptr) + if (InitialTargetStmt == nullptr) return; - const auto *FuncDecl = dyn_cast(DeclCtx); - if (FuncDecl == nullptr) + if (InitialTargetFunc == nullptr) { + initFieldsGlobalsAndFuncs(getReferencedDecls(*InitialTargetStmt)); + ResultObjectMap = + std::make_shared(buildResultObjectMap( + DACtx, InitialTargetStmt, getThisPointeeStorageLocation(), + /*LocForRecordReturnValue=*/nullptr)); return; + } - assert(FuncDecl->doesThisDeclarationHaveABody()); - - initFieldsGlobalsAndFuncs(FuncDecl); + initFieldsGlobalsAndFuncs(getReferencedDecls(*InitialTargetFunc)); - for (const auto *ParamDecl : FuncDecl->parameters()) { + for (const auto *ParamDecl : InitialTargetFunc->parameters()) { assert(ParamDecl != nullptr); setStorageLocation(*ParamDecl, createObject(*ParamDecl, nullptr)); } - if (FuncDecl->getReturnType()->isRecordType()) + if (InitialTargetFunc->getReturnType()->isRecordType()) LocForRecordReturnVal = &cast( - createStorageLocation(FuncDecl->getReturnType())); + createStorageLocation(InitialTargetFunc->getReturnType())); - if (const auto *MethodDecl = dyn_cast(DeclCtx)) { + if (const auto *MethodDecl = dyn_cast(InitialTargetFunc)) { auto *Parent = MethodDecl->getParent(); assert(Parent != nullptr); @@ -558,7 +554,7 @@ void Environment::initialize() { setStorageLocation(*VarDecl, createObject(*VarDecl, nullptr)); } else if (Capture.capturesThis()) { const auto *SurroundingMethodDecl = - cast(DeclCtx->getNonClosureAncestor()); + cast(InitialTargetFunc->getNonClosureAncestor()); QualType ThisPointeeType = SurroundingMethodDecl->getFunctionObjectParameterType(); setThisPointeeStorageLocation( @@ -580,18 +576,16 @@ void Environment::initialize() { // We do this below the handling of `CXXMethodDecl` above so that we can // be sure that the storage location for `this` has been set. - ResultObjectMap = std::make_shared( - buildResultObjectMap(DACtx, FuncDecl, getThisPointeeStorageLocation(), - LocForRecordReturnVal)); + ResultObjectMap = + std::make_shared(buildResultObjectMap( + DACtx, InitialTargetFunc, getThisPointeeStorageLocation(), + LocForRecordReturnVal)); } -// FIXME: Add support for resetting globals after function calls to enable -// the implementation of sound analyses. -void Environment::initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl) { - assert(FuncDecl->doesThisDeclarationHaveABody()); - - ReferencedDecls Referenced = getReferencedDecls(*FuncDecl); +// FIXME: Add support for resetting globals after function calls to enable the +// implementation of sound analyses. +void Environment::initFieldsGlobalsAndFuncs(const ReferencedDecls &Referenced) { // These have to be added before the lines that follow to ensure that // `create*` work correctly for structs. DACtx->addModeledFields(Referenced.Fields); @@ -602,9 +596,9 @@ void Environment::initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl) { // We don't run transfer functions on the initializers of global variables, // so they won't be associated with a value or storage location. We - // therefore intentionally don't pass an initializer to `createObject()`; - // in particular, this ensures that `createObject()` will initialize the - // fields of record-type variables with values. + // therefore intentionally don't pass an initializer to `createObject()`; in + // particular, this ensures that `createObject()` will initialize the fields + // of record-type variables with values. setStorageLocation(*D, createObject(*D, nullptr)); } @@ -623,8 +617,8 @@ Environment Environment::fork() const { } bool Environment::canDescend(unsigned MaxDepth, - const DeclContext *Callee) const { - return CallStack.size() <= MaxDepth && !llvm::is_contained(CallStack, Callee); + const FunctionDecl *Callee) const { + return CallStack.size() < MaxDepth && !llvm::is_contained(CallStack, Callee); } Environment Environment::pushCall(const CallExpr *Call) const { @@ -671,7 +665,7 @@ void Environment::pushCallInternal(const FunctionDecl *FuncDecl, CallStack.push_back(FuncDecl); - initFieldsGlobalsAndFuncs(FuncDecl); + initFieldsGlobalsAndFuncs(getReferencedDecls(*FuncDecl)); const auto *ParamIt = FuncDecl->param_begin(); @@ -755,6 +749,8 @@ LatticeEffect Environment::widen(const Environment &PrevEnv, assert(ThisPointeeLoc == PrevEnv.ThisPointeeLoc); assert(CallStack == PrevEnv.CallStack); assert(ResultObjectMap == PrevEnv.ResultObjectMap); + assert(InitialTargetFunc == PrevEnv.InitialTargetFunc); + assert(InitialTargetStmt == PrevEnv.InitialTargetStmt); auto Effect = LatticeEffect::Unchanged; @@ -790,6 +786,8 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB, assert(EnvA.ThisPointeeLoc == EnvB.ThisPointeeLoc); assert(EnvA.CallStack == EnvB.CallStack); assert(EnvA.ResultObjectMap == EnvB.ResultObjectMap); + assert(EnvA.InitialTargetFunc == EnvB.InitialTargetFunc); + assert(EnvA.InitialTargetStmt == EnvB.InitialTargetStmt); Environment JoinedEnv(*EnvA.DACtx); @@ -797,14 +795,13 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB, JoinedEnv.ResultObjectMap = EnvA.ResultObjectMap; JoinedEnv.LocForRecordReturnVal = EnvA.LocForRecordReturnVal; JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc; + JoinedEnv.InitialTargetFunc = EnvA.InitialTargetFunc; + JoinedEnv.InitialTargetStmt = EnvA.InitialTargetStmt; - if (EnvA.CallStack.empty()) { + const FunctionDecl *Func = EnvA.getCurrentFunc(); + if (!Func) { JoinedEnv.ReturnVal = nullptr; } else { - // FIXME: Make `CallStack` a vector of `FunctionDecl` so we don't need this - // cast. - auto *Func = dyn_cast(EnvA.CallStack.back()); - assert(Func != nullptr); JoinedEnv.ReturnVal = joinValues(Func->getReturnType(), EnvA.ReturnVal, EnvA, EnvB.ReturnVal, EnvB, JoinedEnv, Model); @@ -1229,16 +1226,26 @@ Environment::PrValueToResultObject Environment::buildResultObjectMap( RecordStorageLocation *LocForRecordReturnVal) { assert(FuncDecl->doesThisDeclarationHaveABody()); - PrValueToResultObject Map; + PrValueToResultObject Map = buildResultObjectMap( + DACtx, FuncDecl->getBody(), ThisPointeeLoc, LocForRecordReturnVal); ResultObjectVisitor Visitor(Map, LocForRecordReturnVal, *DACtx); if (const auto *Ctor = dyn_cast(FuncDecl)) Visitor.TraverseConstructorInits(Ctor, ThisPointeeLoc); - Visitor.TraverseStmt(FuncDecl->getBody()); return Map; } +Environment::PrValueToResultObject Environment::buildResultObjectMap( + DataflowAnalysisContext *DACtx, Stmt *S, + RecordStorageLocation *ThisPointeeLoc, + RecordStorageLocation *LocForRecordReturnVal) { + PrValueToResultObject Map; + ResultObjectVisitor Visitor(Map, LocForRecordReturnVal, *DACtx); + Visitor.TraverseStmt(S); + return Map; +} + RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE, const Environment &Env) { Expr *ImplicitObject = MCE.getImplicitObjectArgument(); diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp index 12eff4dd4b781d8acf3f64b477b5ee52a1d25d07..675b42550f17723a8bf97ff728ccf66ede36b778 100644 --- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -476,7 +476,7 @@ runTypeErasedDataflowAnalysis( PrettyStackTraceAnalysis CrashInfo(ACFG, "runTypeErasedDataflowAnalysis"); std::optional MaybeStartingEnv; - if (InitEnv.callStackSize() == 1) { + if (InitEnv.callStackSize() == 0) { MaybeStartingEnv = InitEnv.fork(); MaybeStartingEnv->initialize(); } diff --git a/clang/lib/Analysis/ThreadSafetyCommon.cpp b/clang/lib/Analysis/ThreadSafetyCommon.cpp index 33f1f466df24440bb91981179d886b93afeac370..3e8c959ccee4f653e6992493bc429a6e4f2f2b2e 100644 --- a/clang/lib/Analysis/ThreadSafetyCommon.cpp +++ b/clang/lib/Analysis/ThreadSafetyCommon.cpp @@ -177,7 +177,7 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp, return CapabilityExpr(); if (const auto* SLit = dyn_cast(AttrExp)) { - if (SLit->getString() == StringRef("*")) + if (SLit->getString() == "*") // The "*" expr is a universal lock, which essentially turns off // checks until it is removed from the lockset. return CapabilityExpr(new (Arena) til::Wildcard(), StringRef("wildcard"), @@ -197,7 +197,7 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp, else if (const auto *UO = dyn_cast(AttrExp)) { if (UO->getOpcode() == UO_LNot) { Neg = true; - AttrExp = UO->getSubExpr(); + AttrExp = UO->getSubExpr()->IgnoreImplicit(); } } diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index c42e70d5b95ac1b98c5a10bd3e0f584be076fa43..866222380974b69edb39a2a2eb1dc88e5dec560a 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -492,7 +492,9 @@ public: #endif virtual bool isWarningGadget() const = 0; - virtual const Stmt *getBaseStmt() const = 0; + // TODO remove this method from WarningGadget interface. It's only used for + // debug prints in FixableGadget. + virtual SourceLocation getSourceLoc() const = 0; /// Returns the list of pointer-type variables on which this gadget performs /// its operation. Typically, there's only one variable. This isn't a list @@ -513,6 +515,10 @@ public: static bool classof(const Gadget *G) { return G->isWarningGadget(); } bool isWarningGadget() const final { return true; } + + virtual void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const = 0; }; /// Fixable gadgets correspond to code patterns that aren't always unsafe but @@ -572,7 +578,12 @@ public: .bind(OpTag)); } - const UnaryOperator *getBaseStmt() const override { return Op; } + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperation(Op, IsRelatedToDecl, Ctx); + } + SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { SmallVector Uses; @@ -607,7 +618,12 @@ public: .bind(OpTag)); } - const UnaryOperator *getBaseStmt() const override { return Op; } + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperation(Op, IsRelatedToDecl, Ctx); + } + SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { if (const auto *DRE = @@ -648,7 +664,12 @@ public: // clang-format on } - const ArraySubscriptExpr *getBaseStmt() const override { return ASE; } + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperation(ASE, IsRelatedToDecl, Ctx); + } + SourceLocation getSourceLoc() const override { return ASE->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { if (const auto *DRE = @@ -696,7 +717,12 @@ public: .bind(PointerArithmeticTag)); } - const Stmt *getBaseStmt() const override { return PA; } + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperation(PA, IsRelatedToDecl, Ctx); + } + SourceLocation getSourceLoc() const override { return PA->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { if (const auto *DRE = dyn_cast(Ptr->IgnoreParenImpCasts())) { @@ -734,7 +760,12 @@ public: .bind(SpanTwoParamConstructorTag)); } - const Stmt *getBaseStmt() const override { return Ctor; } + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperationInContainer(Ctor, IsRelatedToDecl, Ctx); + } + SourceLocation getSourceLoc() const override { return Ctor->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { // If the constructor call is of the form `std::span{var, n}`, `var` is @@ -780,11 +811,8 @@ public: virtual std::optional getFixits(const FixitStrategy &S) const override; - - virtual const Stmt *getBaseStmt() const override { - // FIXME: This needs to be the entire DeclStmt, assuming that this method - // makes sense at all on a FixableGadget. - return PtrInitRHS; + SourceLocation getSourceLoc() const override { + return PtrInitRHS->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { @@ -833,12 +861,7 @@ public: virtual std::optional getFixits(const FixitStrategy &S) const override; - - virtual const Stmt *getBaseStmt() const override { - // FIXME: This should be the binary operator, assuming that this method - // makes sense at all on a FixableGadget. - return PtrLHS; - } + SourceLocation getSourceLoc() const override { return PtrLHS->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { return DeclUseList{PtrLHS, PtrRHS}; @@ -888,12 +911,7 @@ public: virtual std::optional getFixits(const FixitStrategy &S) const override; - - virtual const Stmt *getBaseStmt() const override { - // FIXME: This should be the binary operator, assuming that this method - // makes sense at all on a FixableGadget. - return PtrLHS; - } + SourceLocation getSourceLoc() const override { return PtrLHS->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { return DeclUseList{PtrLHS, PtrRHS}; @@ -921,10 +939,53 @@ public: } static Matcher matcher() { - return stmt(callExpr(callee(functionDecl(hasAttr(attr::UnsafeBufferUsage)))) - .bind(OpTag)); + auto HasUnsafeFnDecl = + callee(functionDecl(hasAttr(attr::UnsafeBufferUsage))); + return stmt(callExpr(HasUnsafeFnDecl).bind(OpTag)); + } + + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperation(Op, IsRelatedToDecl, Ctx); } - const Stmt *getBaseStmt() const override { return Op; } + SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); } + + DeclUseList getClaimedVarUseSites() const override { return {}; } +}; + +/// A call of a constructor that performs unchecked buffer operations +/// over one of its pointer parameters, or constructs a class object that will +/// perform buffer operations that depend on the correctness of the parameters. +class UnsafeBufferUsageCtorAttrGadget : public WarningGadget { + constexpr static const char *const OpTag = "cxx_construct_expr"; + const CXXConstructExpr *Op; + +public: + UnsafeBufferUsageCtorAttrGadget(const MatchFinder::MatchResult &Result) + : WarningGadget(Kind::UnsafeBufferUsageCtorAttr), + Op(Result.Nodes.getNodeAs(OpTag)) {} + + static bool classof(const Gadget *G) { + return G->getKind() == Kind::UnsafeBufferUsageCtorAttr; + } + + static Matcher matcher() { + auto HasUnsafeCtorDecl = + hasDeclaration(cxxConstructorDecl(hasAttr(attr::UnsafeBufferUsage))); + // std::span(ptr, size) ctor is handled by SpanTwoParamConstructorGadget. + auto HasTwoParamSpanCtorDecl = SpanTwoParamConstructorGadget::matcher(); + return stmt( + cxxConstructExpr(HasUnsafeCtorDecl, unless(HasTwoParamSpanCtorDecl)) + .bind(OpTag)); + } + + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperation(Op, IsRelatedToDecl, Ctx); + } + SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { return {}; } }; @@ -953,7 +1014,13 @@ public: explicitCastExpr(anyOf(has(callExpr), has(parenExpr(has(callExpr))))) .bind(OpTag)); } - const Stmt *getBaseStmt() const override { return Op; } + + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperation(Op, IsRelatedToDecl, Ctx); + } + SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { return {}; } }; @@ -990,8 +1057,7 @@ public: virtual std::optional getFixits(const FixitStrategy &S) const override; - - virtual const Stmt *getBaseStmt() const override { return Node; } + SourceLocation getSourceLoc() const override { return Node->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { if (const auto *DRE = @@ -1031,8 +1097,7 @@ public: virtual std::optional getFixits(const FixitStrategy &S) const override; - - virtual const Stmt *getBaseStmt() const override { return Node; } + SourceLocation getSourceLoc() const override { return Node->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { return {Node}; } }; @@ -1070,10 +1135,9 @@ public: return {BaseDeclRefExpr}; } - virtual const Stmt *getBaseStmt() const final { return Op; } - virtual std::optional getFixits(const FixitStrategy &S) const override; + SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); } }; // Represents expressions of the form `&DRE[any]` in the Unspecified Pointer @@ -1108,8 +1172,7 @@ public: virtual std::optional getFixits(const FixitStrategy &) const override; - - virtual const Stmt *getBaseStmt() const override { return Node; } + SourceLocation getSourceLoc() const override { return Node->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { const auto *ArraySubst = cast(Node->getSubExpr()); @@ -1218,8 +1281,7 @@ public: virtual std::optional getFixits(const FixitStrategy &S) const override; - - virtual const Stmt *getBaseStmt() const override { return Node; } + SourceLocation getSourceLoc() const override { return Node->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { return {dyn_cast(Node->getSubExpr())}; @@ -1264,8 +1326,7 @@ public: virtual std::optional getFixits(const FixitStrategy &S) const override; - - virtual const Stmt *getBaseStmt() const override { return Node; } + SourceLocation getSourceLoc() const override { return Node->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { return {dyn_cast(Node->getLHS())}; @@ -1315,9 +1376,9 @@ public: virtual std::optional getFixits(const FixitStrategy &s) const final; - - // TODO remove this method from FixableGadget interface - virtual const Stmt *getBaseStmt() const final { return nullptr; } + SourceLocation getSourceLoc() const override { + return DerefOp->getBeginLoc(); + } virtual DeclUseList getClaimedVarUseSites() const final { return {BaseDeclRefExpr}; @@ -2070,7 +2131,7 @@ UUCAddAssignGadget::getFixits(const FixitStrategy &S) const { if (S.lookup(VD) == FixitStrategy::Kind::Span) { FixItList Fixes; - const Stmt *AddAssignNode = getBaseStmt(); + const Stmt *AddAssignNode = Node; StringRef varName = VD->getName(); const ASTContext &Ctx = VD->getASTContext(); @@ -2112,7 +2173,6 @@ UPCPreIncrementGadget::getFixits(const FixitStrategy &S) const { if (S.lookup(VD) == FixitStrategy::Kind::Span) { FixItList Fixes; std::stringstream SS; - const Stmt *PreIncNode = getBaseStmt(); StringRef varName = VD->getName(); const ASTContext &Ctx = VD->getASTContext(); @@ -2120,12 +2180,12 @@ UPCPreIncrementGadget::getFixits(const FixitStrategy &S) const { SS << "(" << varName.data() << " = " << varName.data() << ".subspan(1)).data()"; std::optional PreIncLocation = - getEndCharLoc(PreIncNode, Ctx.getSourceManager(), Ctx.getLangOpts()); + getEndCharLoc(Node, Ctx.getSourceManager(), Ctx.getLangOpts()); if (!PreIncLocation) return std::nullopt; Fixes.push_back(FixItHint::CreateReplacement( - SourceRange(PreIncNode->getBeginLoc(), *PreIncLocation), SS.str())); + SourceRange(Node->getBeginLoc(), *PreIncLocation), SS.str())); return Fixes; } } @@ -2856,7 +2916,7 @@ getFixIts(FixableGadgetSets &FixablesForAllVars, const FixitStrategy &S, } #ifndef NDEBUG Handler.addDebugNoteForVar( - VD, F->getBaseStmt()->getBeginLoc(), + VD, F->getSourceLoc(), ("gadget '" + F->getDebugName() + "' refused to produce a fix") .str()); #endif @@ -3008,8 +3068,8 @@ void clang::checkUnsafeBufferUsage(const Decl *D, // every problematic operation and consider it done. No need to deal // with fixable gadgets, no need to group operations by variable. for (const auto &G : WarningGadgets) { - Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/false, - D->getASTContext()); + G->handleUnsafeOperation(Handler, /*IsRelatedToDecl=*/false, + D->getASTContext()); } // This return guarantees that most of the machine doesn't run when @@ -3251,8 +3311,8 @@ void clang::checkUnsafeBufferUsage(const Decl *D, Tracker, Handler, VarGrpMgr); for (const auto &G : UnsafeOps.noVar) { - Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/false, - D->getASTContext()); + G->handleUnsafeOperation(Handler, /*IsRelatedToDecl=*/false, + D->getASTContext()); } for (const auto &[VD, WarningGadgets] : UnsafeOps.byVar) { @@ -3263,8 +3323,8 @@ void clang::checkUnsafeBufferUsage(const Decl *D, : FixItList{}, D, NaiveStrategy); for (const auto &G : WarningGadgets) { - Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/true, - D->getASTContext()); + G->handleUnsafeOperation(Handler, /*IsRelatedToDecl=*/true, + D->getASTContext()); } } } diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index 37734d3b10e78f767195558ab4d6e599e787a961..753601e01b5c300a37544a25c49531274872e0b4 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -276,14 +276,14 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, std::pair LocInfo = getDecomposedExpansionLoc(Loc); bool Invalid = false; - const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); + SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); if (!Entry.isFile() || Invalid) return; - const SrcMgr::FileInfo &FileInfo = Entry.getFile(); + SrcMgr::FileInfo &FileInfo = Entry.getFile(); // Remember that this file has #line directives now if it doesn't already. - const_cast(FileInfo).setHasLineDirectives(); + FileInfo.setHasLineDirectives(); (void) getLineTable(); @@ -431,6 +431,10 @@ ContentCache &SourceManager::createMemBufferContentCache( const SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index, bool *Invalid) const { + return const_cast(this)->loadSLocEntry(Index, Invalid); +} + +SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index, bool *Invalid) { assert(!SLocEntryLoaded[Index]); if (ExternalSLocEntries->ReadSLocEntry(-(static_cast(Index) + 2))) { if (Invalid) diff --git a/clang/lib/Basic/Targets/Mips.h b/clang/lib/Basic/Targets/Mips.h index 730deb674aa5795af5e41df7d1382095900e3788..f76c6ece8bf481acef61df26f585812f2fd27c2a 100644 --- a/clang/lib/Basic/Targets/Mips.h +++ b/clang/lib/Basic/Targets/Mips.h @@ -85,8 +85,13 @@ public: return CPU == "mips32r6" || CPU == "mips64r6"; } - bool isFP64Default() const { - return CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64"; + enum FPModeEnum getDefaultFPMode() const { + if (CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64") + return FP64; + else if (CPU == "mips1") + return FP32; + else + return FPXX; } bool isNan2008() const override { return IsNan2008; } @@ -315,8 +320,8 @@ public: IsSingleFloat = false; FloatABI = HardFloat; DspRev = NoDSP; - FPMode = isFP64Default() ? FP64 : FPXX; NoOddSpreg = false; + FPMode = getDefaultFPMode(); bool OddSpregGiven = false; bool StrictAlign = false; diff --git a/clang/lib/Basic/TypeTraits.cpp b/clang/lib/Basic/TypeTraits.cpp index 4dbf678dc395bed814c8961667c4876b6edcd151..8d6794223ccaf9eab5e59b9c38089685880576d7 100644 --- a/clang/lib/Basic/TypeTraits.cpp +++ b/clang/lib/Basic/TypeTraits.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/TypeTraits.h" #include "llvm/Support/ErrorHandling.h" #include +#include using namespace clang; static constexpr const char *TypeTraitNames[] = { @@ -81,6 +82,15 @@ const char *clang::getTraitName(UnaryExprOrTypeTrait T) { const char *clang::getTraitSpelling(TypeTrait T) { assert(T <= TT_Last && "invalid enum value!"); + if (T == BTT_IsDeducible) { + // The __is_deducible is an internal-only type trait. To hide it from + // external users, we define it with an empty spelling name, preventing the + // clang parser from recognizing its token kind. + // However, other components such as the AST dump still require the real + // type trait name. Therefore, we return the real name when needed. + assert(std::strlen(TypeTraitSpellings[T]) == 0); + return "__is_deducible"; + } return TypeTraitSpellings[T]; } diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 34f289334a7df90584d9b7f80bf57a99060a7af0..8acda3f2eb864a8137644b7c96fd80c81cad2d1a 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -1052,7 +1052,8 @@ static void emitWasmCatchPadBlock(CodeGenFunction &CGF, CGF.Builder.CreateStore(Exn, CGF.getExceptionSlot()); llvm::CallInst *Selector = CGF.Builder.CreateCall(GetSelectorFn, CPI); - llvm::Function *TypeIDFn = CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); + llvm::Function *TypeIDFn = + CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for, {CGF.VoidPtrTy}); // If there's only a single catch-all, branch directly to its handler. if (CatchScope.getNumHandlers() == 1 && @@ -1137,7 +1138,7 @@ static void emitCatchDispatchBlock(CodeGenFunction &CGF, // Select the right handler. llvm::Function *llvm_eh_typeid_for = - CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); + CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for, {CGF.VoidPtrTy}); llvm::Type *argTy = llvm_eh_typeid_for->getArg(0)->getType(); LangAS globAS = CGF.CGM.GetGlobalVarAddressSpace(nullptr); diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index c18c36d3f3f3267fba9906f2c81092b8bfe3ff94..0cfdb7effe470345b8340de48666c6191db1dedb 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -2216,7 +2216,12 @@ static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, } llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) { - llvm::Type *PtrTy = llvm::PointerType::getUnqual(getLLVMContext()); + // Ideally, we would like to use GlobalsInt8PtrTy here, however, we cannot, + // primarily because the result of applying typeid is a value of type + // type_info, which is declared & defined by the standard library + // implementation and expects to operate on the generic (default) AS. + // https://reviews.llvm.org/D157452 has more context, and a possible solution. + llvm::Type *PtrTy = Int8PtrTy; LangAS GlobAS = CGM.GetGlobalVarAddressSpace(nullptr); auto MaybeASCast = [=](auto &&TypeInfo) { diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 94962091116afbb2927c5ebe4ce81d5497a0e579..4eb65b34a89f56b60984dee3585c9144b25ffe35 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -393,7 +393,7 @@ bool ConstantAggregateBuilder::split(size_t Index, CharUnits Hint) { static llvm::Constant * EmitArrayConstant(CodeGenModule &CGM, llvm::ArrayType *DesiredType, - llvm::Type *CommonElementType, unsigned ArrayBound, + llvm::Type *CommonElementType, uint64_t ArrayBound, SmallVectorImpl &Elements, llvm::Constant *Filler); @@ -949,11 +949,11 @@ tryEmitGlobalCompoundLiteral(ConstantEmitter &emitter, static llvm::Constant * EmitArrayConstant(CodeGenModule &CGM, llvm::ArrayType *DesiredType, - llvm::Type *CommonElementType, unsigned ArrayBound, + llvm::Type *CommonElementType, uint64_t ArrayBound, SmallVectorImpl &Elements, llvm::Constant *Filler) { // Figure out how long the initial prefix of non-zero elements is. - unsigned NonzeroLength = ArrayBound; + uint64_t NonzeroLength = ArrayBound; if (Elements.size() < NonzeroLength && Filler->isNullValue()) NonzeroLength = Elements.size(); if (NonzeroLength == Elements.size()) { @@ -965,7 +965,7 @@ EmitArrayConstant(CodeGenModule &CGM, llvm::ArrayType *DesiredType, return llvm::ConstantAggregateZero::get(DesiredType); // Add a zeroinitializer array filler if we have lots of trailing zeroes. - unsigned TrailingZeroes = ArrayBound - NonzeroLength; + uint64_t TrailingZeroes = ArrayBound - NonzeroLength; if (TrailingZeroes >= 8) { assert(Elements.size() >= NonzeroLength && "missing initializer for non-zero element"); @@ -1252,12 +1252,12 @@ public: llvm::Constant *EmitArrayInitialization(const InitListExpr *ILE, QualType T) { auto *CAT = CGM.getContext().getAsConstantArrayType(ILE->getType()); assert(CAT && "can't emit array init for non-constant-bound array"); - unsigned NumInitElements = ILE->getNumInits(); - unsigned NumElements = CAT->getZExtSize(); + const uint64_t NumElements = CAT->getZExtSize(); // Initialising an array requires us to automatically // initialise any elements that have not been initialised explicitly - unsigned NumInitableElts = std::min(NumInitElements, NumElements); + uint64_t NumInitableElts = + std::min(ILE->getNumInits(), NumElements); QualType EltType = CAT->getElementType(); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 34dc0bd5c15bcd9015f6f9d68a89157b1033997f..04abdadd95379e1f6bb79f0d816876fed356f668 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -985,6 +985,11 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, EmitKernelMetadata(FD, Fn); } + if (FD && FD->hasAttr()) { + Fn->setMetadata("clspv_libclc_builtin", + llvm::MDNode::get(getLLVMContext(), {})); + } + // If we are checking function types, emit a function type signature as // prologue data. if (FD && SanOpts.has(SanitizerKind::Function)) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 362f4a5fe72a6327eeda4a61a3d6e57070905222..5f3ee7eb943f9e17aa7a5a20579f6324228d1eda 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -137,7 +137,8 @@ enum TypeEvaluationKind { SANITIZER_CHECK(SubOverflow, sub_overflow, 0) \ SANITIZER_CHECK(TypeMismatch, type_mismatch, 1) \ SANITIZER_CHECK(AlignmentAssumption, alignment_assumption, 0) \ - SANITIZER_CHECK(VLABoundNotPositive, vla_bound_not_positive, 0) + SANITIZER_CHECK(VLABoundNotPositive, vla_bound_not_positive, 0) \ + SANITIZER_CHECK(BoundsSafety, bounds_safety, 0) enum SanitizerHandler { #define SANITIZER_CHECK(Enum, Name, Version) Enum, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 489c08a4d4819bdb1309a08748f40589b34302c5..227813ad44e8b8feaed2c4bb7dfbeadad61c8261 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -368,7 +368,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, IntTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getIntWidth()); IntPtrTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getMaxPointerWidth()); - Int8PtrTy = llvm::PointerType::get(LLVMContext, 0); + Int8PtrTy = llvm::PointerType::get(LLVMContext, + C.getTargetAddressSpace(LangAS::Default)); const llvm::DataLayout &DL = M.getDataLayout(); AllocaInt8PtrTy = llvm::PointerType::get(LLVMContext, DL.getAllocaAddrSpace()); diff --git a/clang/lib/CodeGen/CodeGenTypeCache.h b/clang/lib/CodeGen/CodeGenTypeCache.h index 083d69214fb3c29ca8bdca7987b59493b19091a1..e273ebe3b060f2288a167005fa3c06c5e036c475 100644 --- a/clang/lib/CodeGen/CodeGenTypeCache.h +++ b/clang/lib/CodeGen/CodeGenTypeCache.h @@ -51,7 +51,7 @@ struct CodeGenTypeCache { llvm::IntegerType *PtrDiffTy; }; - /// void*, void** in address space 0 + /// void*, void** in the target's default address space (often 0) union { llvm::PointerType *UnqualPtrTy; llvm::PointerType *VoidPtrTy; diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index ce2f39aeb082137771f4fa9b46e20a499d0246df..f4de21bac4b466e943c9fefb042fff3858e801a6 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -17,6 +17,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Lex/Lexer.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ProfileData/Coverage/CoverageMapping.h" @@ -336,16 +337,26 @@ public: llvm::SmallSet Visited; SmallVector, 8> FileLocs; - for (const auto &Region : SourceRegions) { + for (auto &Region : SourceRegions) { SourceLocation Loc = Region.getBeginLoc(); + + // Replace Loc with FileLoc if it is expanded with system headers. + if (!SystemHeadersCoverage && SM.isInSystemMacro(Loc)) { + auto BeginLoc = SM.getSpellingLoc(Loc); + auto EndLoc = SM.getSpellingLoc(Region.getEndLoc()); + if (SM.isWrittenInSameFile(BeginLoc, EndLoc)) { + Loc = SM.getFileLoc(Loc); + Region.setStartLoc(Loc); + Region.setEndLoc(SM.getFileLoc(Region.getEndLoc())); + } + } + FileID File = SM.getFileID(Loc); if (!Visited.insert(File).second) continue; - // Do not map FileID's associated with system headers unless collecting - // coverage from system headers is explicitly enabled. - if (!SystemHeadersCoverage && SM.isInSystemHeader(SM.getSpellingLoc(Loc))) - continue; + assert(SystemHeadersCoverage || + !SM.isInSystemHeader(SM.getSpellingLoc(Loc))); unsigned Depth = 0; for (SourceLocation Parent = getIncludeOrExpansionLoc(Loc); @@ -818,6 +829,10 @@ struct CounterCoverageMappingBuilder /// A stack of currently live regions. llvm::SmallVector RegionStack; + /// Set if the Expr should be handled as a leaf even if it is kind of binary + /// logical ops (&&, ||). + llvm::DenseSet LeafExprSet; + /// An object to manage MCDC regions. MCDCCoverageBuilder MCDCBuilder; @@ -1040,7 +1055,10 @@ struct CounterCoverageMappingBuilder // region onto RegionStack but immediately pop it (which adds it to the // function's SourceRegions) because it doesn't apply to any other source // code other than the Condition. - if (CodeGenFunction::isInstrumentedCondition(C)) { + // With !SystemHeadersCoverage, binary logical ops in system headers may be + // treated as instrumentable conditions. + if (CodeGenFunction::isInstrumentedCondition(C) || + LeafExprSet.count(CodeGenFunction::stripCond(C))) { mcdc::Parameters BranchParams; mcdc::ConditionID ID = MCDCBuilder.getCondID(C); if (ID >= 0) @@ -1439,6 +1457,10 @@ struct CounterCoverageMappingBuilder terminateRegion(S); } + void VisitCoroutineSuspendExpr(const CoroutineSuspendExpr *E) { + Visit(E->getOperand()); + } + void VisitCXXThrowExpr(const CXXThrowExpr *E) { extendRegion(E); if (E->getSubExpr()) @@ -2066,7 +2088,20 @@ struct CounterCoverageMappingBuilder createDecisionRegion(E, DecisionParams); } + /// Check if E belongs to system headers. + bool isExprInSystemHeader(const BinaryOperator *E) const { + return (!SystemHeadersCoverage && + SM.isInSystemHeader(SM.getSpellingLoc(E->getOperatorLoc())) && + SM.isInSystemHeader(SM.getSpellingLoc(E->getBeginLoc())) && + SM.isInSystemHeader(SM.getSpellingLoc(E->getEndLoc()))); + } + void VisitBinLAnd(const BinaryOperator *E) { + if (isExprInSystemHeader(E)) { + LeafExprSet.insert(E); + return; + } + bool IsRootNode = MCDCBuilder.isIdle(); // Keep track of Binary Operator and assign MCDC condition IDs. @@ -2121,6 +2156,11 @@ struct CounterCoverageMappingBuilder } void VisitBinLOr(const BinaryOperator *E) { + if (isExprInSystemHeader(E)) { + LeafExprSet.insert(E); + return; + } + bool IsRootNode = MCDCBuilder.isIdle(); // Keep track of Binary Operator and assign MCDC condition IDs. @@ -2173,6 +2213,10 @@ struct CounterCoverageMappingBuilder // propagate counts into them. } + void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *AILE) { + Visit(AILE->getCommonExpr()->getSourceExpr()); + } + void VisitPseudoObjectExpr(const PseudoObjectExpr *POE) { // Just visit syntatic expression as this is what users actually write. VisitStmt(POE->getSyntacticForm()); diff --git a/clang/lib/Driver/ToolChains/Arch/Mips.cpp b/clang/lib/Driver/ToolChains/Arch/Mips.cpp index 74a8874a3ea2b79b1e99d1cb161184a7b340a2d4..79a00711e6f53c6c16589dec82fd65a1b24ae4ed 100644 --- a/clang/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/clang/lib/Driver/ToolChains/Arch/Mips.cpp @@ -369,6 +369,9 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, } else if (mips::isFP64ADefault(Triple, CPUName)) { Features.push_back("+fp64"); Features.push_back("+nooddspreg"); + } else if (Arg *A = Args.getLastArg(options::OPT_mmsa)) { + if (A->getOption().matches(options::OPT_mmsa)) + Features.push_back("+fp64"); } AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg, @@ -499,6 +502,13 @@ bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple, options::OPT_mdouble_float)) if (A->getOption().matches(options::OPT_msingle_float)) UseFPXX = false; + // FP64 should be used for MSA. + if (Arg *A = Args.getLastArg(options::OPT_mmsa)) + if (A->getOption().matches(options::OPT_mmsa)) + UseFPXX = llvm::StringSwitch(CPUName) + .Cases("mips32r2", "mips32r3", "mips32r5", false) + .Cases("mips64r2", "mips64r3", "mips64r5", false) + .Default(UseFPXX); return UseFPXX; } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 42feb1650574ed82a405fd00544ac47c451a04a4..6d2015b2cd15660c0f4908e864998316fa3b3580 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1522,7 +1522,7 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, auto isPAuthLR = [](const char *member) { llvm::AArch64::ExtensionInfo pauthlr_extension = llvm::AArch64::getExtensionByID(llvm::AArch64::AEK_PAUTHLR); - return (pauthlr_extension.Feature.compare(member) == 0); + return pauthlr_extension.Feature == member; }; if (std::any_of(CmdArgs.begin(), CmdArgs.end(), isPAuthLR)) @@ -7253,10 +7253,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_frelaxed_template_template_args, options::OPT_fno_relaxed_template_template_args)) { - D.Diag(diag::warn_drv_deprecated_arg) - << A->getAsString(Args) << /*hasReplacement=*/false; - if (A->getOption().matches(options::OPT_fno_relaxed_template_template_args)) + if (A->getOption().matches( + options::OPT_fno_relaxed_template_template_args)) { + D.Diag(diag::warn_drv_deprecated_arg_no_relaxed_template_template_args); CmdArgs.push_back("-fno-relaxed-template-template-args"); + } else { + D.Diag(diag::warn_drv_deprecated_arg) + << A->getAsString(Args) << /*hasReplacement=*/false; + } } // -fsized-deallocation is off by default, as it is an ABI-breaking change for diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index d275528b6905183345c1624f98334b64b1e2c61e..42ca060186fd8bdce79a4cda14a54305a9ad3127 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -139,6 +139,7 @@ void Flang::addCodegenOptions(const ArgList &Args, Args.addAllArgs(CmdArgs, {options::OPT_flang_experimental_hlfir, options::OPT_flang_deprecated_no_hlfir, + options::OPT_flang_experimental_integer_overflow, options::OPT_fno_ppc_native_vec_elem_order, options::OPT_fppc_native_vec_elem_order}); } diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp index fbf2f45b543844827f388bcd24fc88b9e9b6f842..b7021d4b996dddab71a00021b41d3c196c4ba882 100644 --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -134,6 +134,10 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath)); } + if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L)) + for (const auto &LibPath : Args.getAllArgValues(options::OPT_L)) + CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath)); + if (C.getDriver().IsFlangMode()) { addFortranRuntimeLibraryPath(TC, Args, CmdArgs); addFortranRuntimeLibs(TC, Args, CmdArgs); @@ -154,10 +158,6 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (TC.getVFS().exists(CRTPath)) CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath)); - if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L)) - for (const auto &LibPath : Args.getAllArgValues(options::OPT_L)) - CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath)); - CmdArgs.push_back("-nologo"); if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7)) diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp index 7bf9aa79384c5514b147a54afb08ab0e45920b26..3fd62d9793093781db26e2da65948ce269f0a5ec 100644 --- a/clang/lib/Driver/ToolChains/PS4CPU.cpp +++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp @@ -358,6 +358,12 @@ void toolchains::PS4PS5Base::addClangTargetOptions( CC1Args.push_back("-fno-use-init-array"); + // Default to `hidden` visibility for PS5. + if (getTriple().isPS5() && + !DriverArgs.hasArg(options::OPT_fvisibility_EQ, + options::OPT_fvisibility_ms_compat)) + CC1Args.push_back("-fvisibility=hidden"); + // Default to -fvisibility-global-new-delete=source for PS5. if (getTriple().isPS5() && !DriverArgs.hasArg(options::OPT_fvisibility_global_new_delete_EQ, @@ -376,11 +382,15 @@ void toolchains::PS4PS5Base::addClangTargetOptions( else CC1Args.push_back("-fvisibility-dllexport=protected"); + // For PS4 we override the visibilty of globals definitions without + // dllimport or dllexport annotations. if (DriverArgs.hasArg(options::OPT_fvisibility_nodllstorageclass_EQ)) DriverArgs.AddLastArg(CC1Args, options::OPT_fvisibility_nodllstorageclass_EQ); - else + else if (getTriple().isPS4()) CC1Args.push_back("-fvisibility-nodllstorageclass=hidden"); + else + CC1Args.push_back("-fvisibility-nodllstorageclass=keep"); if (DriverArgs.hasArg(options::OPT_fvisibility_externs_dllimport_EQ)) DriverArgs.AddLastArg(CC1Args, @@ -388,12 +398,16 @@ void toolchains::PS4PS5Base::addClangTargetOptions( else CC1Args.push_back("-fvisibility-externs-dllimport=default"); + // For PS4 we override the visibilty of external globals without + // dllimport or dllexport annotations. if (DriverArgs.hasArg( options::OPT_fvisibility_externs_nodllstorageclass_EQ)) DriverArgs.AddLastArg( CC1Args, options::OPT_fvisibility_externs_nodllstorageclass_EQ); - else + else if (getTriple().isPS4()) CC1Args.push_back("-fvisibility-externs-nodllstorageclass=default"); + else + CC1Args.push_back("-fvisibility-externs-nodllstorageclass=keep"); } } diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 9bf7950888dbb2566fad2c6765695967d1ad58c9..98b9343924a835675dbedd4f4e37c87afab56329 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -12,13 +12,19 @@ //===----------------------------------------------------------------------===// #include "clang/ExtractAPI/DeclarationFragments.h" +#include "clang/AST/ASTFwd.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" #include "clang/Index/USRGeneration.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include using namespace clang::extractapi; using namespace llvm; @@ -386,6 +392,25 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( getFragmentsForType(AT->getElementType(), Context, After)); } + if (const TemplateSpecializationType *TemplSpecTy = + dyn_cast(T)) { + const auto TemplName = TemplSpecTy->getTemplateName(); + std::string Str; + raw_string_ostream Stream(Str); + TemplName.print(Stream, Context.getPrintingPolicy(), + TemplateName::Qualified::AsWritten); + SmallString<64> USR(""); + if (const auto *TemplDecl = TemplName.getAsTemplateDecl()) + index::generateUSRForDecl(TemplDecl, USR); + + return Fragments + .append(Str, DeclarationFragments::FragmentKind::TypeIdentifier, USR) + .append("<", DeclarationFragments::FragmentKind::Text) + .append(getFragmentsForTemplateArguments( + TemplSpecTy->template_arguments(), Context, std::nullopt)) + .append(">", DeclarationFragments::FragmentKind::Text); + } + // Everything we care about has been handled now, reduce to the canonical // unqualified base type. QualType Base = T->getCanonicalTypeUnqualified(); @@ -650,7 +675,6 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock( DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) { DeclarationFragments Fragments; - // FIXME: Handle template specialization switch (Func->getStorageClass()) { case SC_None: case SC_PrivateExtern: @@ -952,27 +976,84 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateParameters( Fragments.append(",", DeclarationFragments::FragmentKind::Text) .appendSpace(); - const auto *TemplateParam = - dyn_cast(ParameterArray[i]); - if (!TemplateParam) - continue; - if (TemplateParam->hasTypeConstraint()) - Fragments.append(TemplateParam->getTypeConstraint() - ->getNamedConcept() - ->getName() - .str(), - DeclarationFragments::FragmentKind::TypeIdentifier); - else if (TemplateParam->wasDeclaredWithTypename()) - Fragments.append("typename", DeclarationFragments::FragmentKind::Keyword); - else - Fragments.append("class", DeclarationFragments::FragmentKind::Keyword); - - if (TemplateParam->isParameterPack()) - Fragments.append("...", DeclarationFragments::FragmentKind::Text); - - Fragments.appendSpace().append( - TemplateParam->getName(), - DeclarationFragments::FragmentKind::GenericParameter); + if (const auto *TemplateParam = + dyn_cast(ParameterArray[i])) { + if (TemplateParam->hasTypeConstraint()) + Fragments.append(TemplateParam->getTypeConstraint() + ->getNamedConcept() + ->getName() + .str(), + DeclarationFragments::FragmentKind::TypeIdentifier); + else if (TemplateParam->wasDeclaredWithTypename()) + Fragments.append("typename", + DeclarationFragments::FragmentKind::Keyword); + else + Fragments.append("class", DeclarationFragments::FragmentKind::Keyword); + + if (TemplateParam->isParameterPack()) + Fragments.append("...", DeclarationFragments::FragmentKind::Text); + + if (!TemplateParam->getName().empty()) + Fragments.appendSpace().append( + TemplateParam->getName(), + DeclarationFragments::FragmentKind::GenericParameter); + + if (TemplateParam->hasDefaultArgument()) { + DeclarationFragments After; + Fragments.append(" = ", DeclarationFragments::FragmentKind::Text) + .append(getFragmentsForType(TemplateParam->getDefaultArgument(), + TemplateParam->getASTContext(), After)); + Fragments.append(std::move(After)); + } + } else if (const auto *NTP = + dyn_cast(ParameterArray[i])) { + DeclarationFragments After; + const auto TyFragments = + getFragmentsForType(NTP->getType(), NTP->getASTContext(), After); + Fragments.append(std::move(TyFragments)).append(std::move(After)); + + if (NTP->isParameterPack()) + Fragments.append("...", DeclarationFragments::FragmentKind::Text); + + if (!NTP->getName().empty()) + Fragments.appendSpace().append( + NTP->getName(), + DeclarationFragments::FragmentKind::GenericParameter); + + if (NTP->hasDefaultArgument()) { + SmallString<8> ExprStr; + raw_svector_ostream Output(ExprStr); + NTP->getDefaultArgument()->printPretty( + Output, nullptr, NTP->getASTContext().getPrintingPolicy()); + Fragments.append(" = ", DeclarationFragments::FragmentKind::Text) + .append(ExprStr, DeclarationFragments::FragmentKind::Text); + } + } else if (const auto *TTP = + dyn_cast(ParameterArray[i])) { + Fragments.append("template", DeclarationFragments::FragmentKind::Keyword) + .appendSpace() + .append("<", DeclarationFragments::FragmentKind::Text) + .append(getFragmentsForTemplateParameters( + TTP->getTemplateParameters()->asArray())) + .append(">", DeclarationFragments::FragmentKind::Text) + .appendSpace() + .append(TTP->wasDeclaredWithTypename() ? "typename" : "class", + DeclarationFragments::FragmentKind::Keyword); + + if (TTP->isParameterPack()) + Fragments.append("...", DeclarationFragments::FragmentKind::Text); + + if (!TTP->getName().empty()) + Fragments.appendSpace().append( + TTP->getName(), + DeclarationFragments::FragmentKind::GenericParameter); + if (TTP->hasDefaultArgument()) { + const auto Default = TTP->getDefaultArgument(); + Fragments.append(" = ", DeclarationFragments::FragmentKind::Text) + .append(getFragmentsForTemplateArguments( + {Default.getArgument()}, TTP->getASTContext(), {Default})); + } + } } return Fragments; } @@ -993,23 +1074,85 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateArguments( Fragments.append(",", DeclarationFragments::FragmentKind::Text) .appendSpace(); - std::string Type = TemplateArguments[i].getAsType().getAsString(); - DeclarationFragments After; - DeclarationFragments ArgumentFragment = - getFragmentsForType(TemplateArguments[i].getAsType(), Context, After); - - if (StringRef(ArgumentFragment.begin()->Spelling) - .starts_with("type-parameter")) { - std::string ProperArgName = TemplateArgumentLocs.value()[i] - .getTypeSourceInfo() - ->getType() - .getAsString(); - ArgumentFragment.begin()->Spelling.swap(ProperArgName); + const auto &CTA = TemplateArguments[i]; + switch (CTA.getKind()) { + case TemplateArgument::Type: { + DeclarationFragments After; + DeclarationFragments ArgumentFragment = + getFragmentsForType(CTA.getAsType(), Context, After); + + if (StringRef(ArgumentFragment.begin()->Spelling) + .starts_with("type-parameter")) { + std::string ProperArgName = TemplateArgumentLocs.value()[i] + .getTypeSourceInfo() + ->getType() + .getAsString(); + ArgumentFragment.begin()->Spelling.swap(ProperArgName); + } + Fragments.append(std::move(ArgumentFragment)); + break; } - Fragments.append(std::move(ArgumentFragment)); + case TemplateArgument::Declaration: { + const auto *VD = CTA.getAsDecl(); + SmallString<128> USR; + index::generateUSRForDecl(VD, USR); + Fragments.append(VD->getNameAsString(), + DeclarationFragments::FragmentKind::Identifier, USR); + break; + } + case TemplateArgument::NullPtr: + Fragments.append("nullptr", DeclarationFragments::FragmentKind::Keyword); + break; - if (TemplateArguments[i].isPackExpansion()) - Fragments.append("...", DeclarationFragments::FragmentKind::Text); + case TemplateArgument::Integral: { + SmallString<4> Str; + CTA.getAsIntegral().toString(Str); + Fragments.append(Str, DeclarationFragments::FragmentKind::Text); + break; + } + + case TemplateArgument::StructuralValue: { + const auto SVTy = CTA.getStructuralValueType(); + Fragments.append(CTA.getAsStructuralValue().getAsString(Context, SVTy), + DeclarationFragments::FragmentKind::Text); + break; + } + + case TemplateArgument::TemplateExpansion: + case TemplateArgument::Template: { + std::string Str; + raw_string_ostream Stream(Str); + CTA.getAsTemplate().print(Stream, Context.getPrintingPolicy()); + SmallString<64> USR(""); + if (const auto *TemplDecl = + CTA.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) + index::generateUSRForDecl(TemplDecl, USR); + Fragments.append(Str, DeclarationFragments::FragmentKind::TypeIdentifier, + USR); + if (CTA.getKind() == TemplateArgument::TemplateExpansion) + Fragments.append("...", DeclarationFragments::FragmentKind::Text); + break; + } + + case TemplateArgument::Pack: + Fragments.append("<", DeclarationFragments::FragmentKind::Text) + .append(getFragmentsForTemplateArguments(CTA.pack_elements(), Context, + {})) + .append(">", DeclarationFragments::FragmentKind::Text); + break; + + case TemplateArgument::Expression: { + SmallString<8> ExprStr; + raw_svector_ostream Output(ExprStr); + CTA.getAsExpr()->printPretty(Output, nullptr, + Context.getPrintingPolicy()); + Fragments.append(ExprStr, DeclarationFragments::FragmentKind::Text); + break; + } + + case TemplateArgument::Null: + break; + } } return Fragments; } @@ -1019,10 +1162,12 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept( DeclarationFragments Fragments; return Fragments .append("template", DeclarationFragments::FragmentKind::Keyword) + .appendSpace() .append("<", DeclarationFragments::FragmentKind::Text) .append(getFragmentsForTemplateParameters( Concept->getTemplateParameters()->asArray())) .append("> ", DeclarationFragments::FragmentKind::Text) + .appendSpace() .append("concept", DeclarationFragments::FragmentKind::Keyword) .appendSpace() .append(Concept->getName().str(), @@ -1035,6 +1180,7 @@ DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate( const RedeclarableTemplateDecl *RedeclarableTemplate) { DeclarationFragments Fragments; Fragments.append("template", DeclarationFragments::FragmentKind::Keyword) + .appendSpace() .append("<", DeclarationFragments::FragmentKind::Text) .append(getFragmentsForTemplateParameters( RedeclarableTemplate->getTemplateParameters()->asArray())) @@ -1057,6 +1203,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization( DeclarationFragments Fragments; return Fragments .append("template", DeclarationFragments::FragmentKind::Keyword) + .appendSpace() .append("<", DeclarationFragments::FragmentKind::Text) .append(">", DeclarationFragments::FragmentKind::Text) .appendSpace() @@ -1077,6 +1224,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization( DeclarationFragments Fragments; return Fragments .append("template", DeclarationFragments::FragmentKind::Keyword) + .appendSpace() .append("<", DeclarationFragments::FragmentKind::Text) .append(getFragmentsForTemplateParameters( Decl->getTemplateParameters()->asArray())) @@ -1099,6 +1247,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization( DeclarationFragments Fragments; return Fragments .append("template", DeclarationFragments::FragmentKind::Keyword) + .appendSpace() .append("<", DeclarationFragments::FragmentKind::Text) .append(">", DeclarationFragments::FragmentKind::Text) .appendSpace() @@ -1118,6 +1267,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization( DeclarationFragments Fragments; return Fragments .append("template", DeclarationFragments::FragmentKind::Keyword) + .appendSpace() .append("<", DeclarationFragments::FragmentKind::Text) // Partial specs may have new params. .append(getFragmentsForTemplateParameters( @@ -1140,6 +1290,7 @@ DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate( DeclarationFragments Fragments; return Fragments .append("template", DeclarationFragments::FragmentKind::Keyword) + .appendSpace() .append("<", DeclarationFragments::FragmentKind::Text) // Partial specs may have new params. .append(getFragmentsForTemplateParameters( @@ -1156,6 +1307,7 @@ DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization( DeclarationFragments Fragments; return Fragments .append("template", DeclarationFragments::FragmentKind::Keyword) + .appendSpace() .append("<>", DeclarationFragments::FragmentKind::Text) .appendSpace() .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl)); diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index c16d4623f115d5892f6abcec5fcceb28c9e59ec6..08e711cafae280c761c35751d7ce0e8d495fe6f2 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -925,6 +925,10 @@ bool SymbolGraphSerializer::visitObjCInterfaceRecord( bool SymbolGraphSerializer::traverseObjCCategoryRecord( const ObjCCategoryRecord *Record) { + if (SkipSymbolsInCategoriesToExternalTypes && + !API.findRecordForUSR(Record->Interface.USR)) + return true; + auto *CurrentModule = ModuleForCurrentSymbol; if (Record->isExtendingExternalModule()) ModuleForCurrentSymbol = &ExtendedModules[Record->Interface.Source]; @@ -1040,8 +1044,11 @@ void SymbolGraphSerializer::serializeGraphToStream( void SymbolGraphSerializer::serializeMainSymbolGraph( raw_ostream &OS, const APISet &API, const APIIgnoresList &IgnoresList, SymbolGraphSerializerOption Options) { - SymbolGraphSerializer Serializer(API, IgnoresList, - Options.EmitSymbolLabelsForTesting); + SymbolGraphSerializer Serializer( + API, IgnoresList, Options.EmitSymbolLabelsForTesting, + /*ForceEmitToMainModule=*/true, + /*SkipSymbolsInCategoriesToExternalTypes=*/true); + Serializer.traverseAPISet(); Serializer.serializeGraphToStream(OS, Options, API.ProductName, std::move(Serializer.MainModule)); diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index d0aa0838423e4f807cfc32b23c1c01a240aa0fdd..7c4c76a91f2c55223324ede7eb880b83d00f60bb 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -5601,10 +5601,13 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, return true; if (Left.IsUnterminatedLiteral) return true; - if (Right.is(tok::lessless) && AfterRight && Left.is(tok::string_literal) && + + if (BeforeLeft && BeforeLeft->is(tok::lessless) && + Left.is(tok::string_literal) && Right.is(tok::lessless) && AfterRight && AfterRight->is(tok::string_literal)) { - return true; + return Right.NewlinesBefore > 0; } + if (Right.is(TT_RequiresClause)) { switch (Style.RequiresClausePosition) { case FormatStyle::RCPS_OwnLine: diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 4f1c2c5114e93287b66a4017ffd9dc30757c849e..b15a87327240bc1a485d4655f65fe5808d84bf22 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -47,7 +47,8 @@ void printLine(llvm::raw_ostream &OS, const UnwrappedLine &Line, OS << Prefix; NewLine = false; } - OS << I->Tok->Tok.getName() << "[" << "T=" << (unsigned)I->Tok->getType() + OS << I->Tok->Tok.getName() << "[" + << "T=" << (unsigned)I->Tok->getType() << ", OC=" << I->Tok->OriginalColumn << ", \"" << I->Tok->TokenText << "\"] "; for (SmallVectorImpl::const_iterator @@ -4007,8 +4008,6 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { }; if (FormatTok->isOneOf(tok::colon, tok::less)) { - if (FormatTok->is(tok::colon)) - IsDerived = true; int AngleNestingLevel = 0; do { if (FormatTok->is(tok::less)) @@ -4016,9 +4015,13 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { else if (FormatTok->is(tok::greater)) --AngleNestingLevel; - if (AngleNestingLevel == 0 && FormatTok->is(tok::l_paren) && - IsNonMacroIdentifier(FormatTok->Previous)) { - break; + if (AngleNestingLevel == 0) { + if (FormatTok->is(tok::colon)) { + IsDerived = true; + } else if (FormatTok->is(tok::l_paren) && + IsNonMacroIdentifier(FormatTok->Previous)) { + break; + } } if (FormatTok->is(tok::l_brace)) { if (AngleNestingLevel == 0 && IsListInitialization()) diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 755aaddc0ad7471659bed1ac10e492afd6ee5810..8d24d5d422520821e5d62484ae990e8f4b686dc2 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -56,6 +56,7 @@ #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Sema/CodeCompleteOptions.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaCodeCompletion.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTWriter.h" @@ -375,8 +376,8 @@ void ASTUnit::CacheCodeCompletionResults() { SmallVector Results; CachedCompletionAllocator = std::make_shared(); CodeCompletionTUInfo CCTUInfo(CachedCompletionAllocator); - TheSema->GatherGlobalCodeCompletions(*CachedCompletionAllocator, - CCTUInfo, Results); + TheSema->CodeCompletion().GatherGlobalCodeCompletions( + *CachedCompletionAllocator, CCTUInfo, Results); // Translate global code completions into cached completions. llvm::DenseMap CompletionTypes; diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 66a45b888f15cc736b11aeba5ee02cac93742ba1..6242b5a7d9fe391b267b0cc8fff8d2e3de0794ae 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -411,8 +411,7 @@ static void InitializeFileRemapping(DiagnosticsEngine &Diags, SourceMgr.overrideFileContents(FromFile, RB.second->getMemBufferRef()); else SourceMgr.overrideFileContents( - FromFile, std::unique_ptr( - const_cast(RB.second))); + FromFile, std::unique_ptr(RB.second)); } // Remap files in the source manager (with other files). diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 3390f0962f67d04670380c54662d644ac5047fb7..bc72e8a00e0d56167d38254a611d981d8cc31e22 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -18,14 +18,21 @@ namespace hlsl { #define _HLSL_BUILTIN_ALIAS(builtin) \ __attribute__((clang_builtin_alias(builtin))) -#define _HLSL_AVAILABILITY(environment, version) \ - __attribute__((availability(environment, introduced = version))) +#define _HLSL_AVAILABILITY(platform, version) \ + __attribute__((availability(platform, introduced = version))) +#define _HLSL_AVAILABILITY_STAGE(platform, version, stage) \ + __attribute__(( \ + availability(platform, introduced = version, environment = stage))) #ifdef __HLSL_ENABLE_16_BIT -#define _HLSL_16BIT_AVAILABILITY(environment, version) \ - __attribute__((availability(environment, introduced = version))) +#define _HLSL_16BIT_AVAILABILITY(platform, version) \ + __attribute__((availability(platform, introduced = version))) +#define _HLSL_16BIT_AVAILABILITY_STAGE(platform, version, stage) \ + __attribute__(( \ + availability(platform, introduced = version, environment = stage))) #else #define _HLSL_16BIT_AVAILABILITY(environment, version) +#define _HLSL_16BIT_AVAILABILITY_STAGE(environment, version, stage) #endif //===----------------------------------------------------------------------===// diff --git a/clang/lib/Headers/opencl-c-base.h b/clang/lib/Headers/opencl-c-base.h index 2494f6213fc5695d9a4c3b70d29ba4f42e0ed7d0..786678b9d8a75320a5473fbe3bf82eff5d0ba4b4 100644 --- a/clang/lib/Headers/opencl-c-base.h +++ b/clang/lib/Headers/opencl-c-base.h @@ -46,6 +46,10 @@ #define __opencl_c_ext_fp32_global_atomic_min_max 1 #define __opencl_c_ext_fp32_local_atomic_min_max 1 #define __opencl_c_ext_image_raw10_raw12 1 +#define cl_khr_kernel_clock 1 +#define __opencl_c_kernel_clock_scope_device 1 +#define __opencl_c_kernel_clock_scope_work_group 1 +#define __opencl_c_kernel_clock_scope_sub_group 1 #endif // defined(__SPIR__) || defined(__SPIRV__) #endif // (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) diff --git a/clang/lib/Headers/opencl-c.h b/clang/lib/Headers/opencl-c.h index 288bb18bc654ebc8208ec6b56fab4fa45019a733..20719b74b6b8d1dcec5e6c2be19d6589b51ea1a1 100644 --- a/clang/lib/Headers/opencl-c.h +++ b/clang/lib/Headers/opencl-c.h @@ -17314,6 +17314,21 @@ half __ovld __conv sub_group_clustered_rotate(half, int, uint); #endif // cl_khr_fp16 #endif // cl_khr_subgroup_rotate +#if defined(cl_khr_kernel_clock) +#if defined(__opencl_c_kernel_clock_scope_device) +ulong __ovld clock_read_device(); +uint2 __ovld clock_read_hilo_device(); +#endif // __opencl_c_kernel_clock_scope_device +#if defined(__opencl_c_kernel_clock_scope_work_group) +ulong __ovld clock_read_work_group(); +uint2 __ovld clock_read_hilo_work_group(); +#endif // __opencl_c_kernel_clock_scope_work_group +#if defined(__opencl_c_kernel_clock_scope_sub_group) +ulong __ovld clock_read_sub_group(); +uint2 __ovld clock_read_hilo_sub_group(); +#endif // __opencl_c_kernel_clock_scope_sub_group +#endif // cl_khr_kernel_clock + #if defined(cl_intel_subgroups) // Intel-Specific Sub Group Functions float __ovld __conv intel_sub_group_shuffle( float , uint ); diff --git a/clang/lib/Index/CommentToXML.cpp b/clang/lib/Index/CommentToXML.cpp index 295f3f228ff79bd2098b90ef3e8899501214d829..3372fbba4383173bfcd97e2c6c156a8cc010dba9 100644 --- a/clang/lib/Index/CommentToXML.cpp +++ b/clang/lib/Index/CommentToXML.cpp @@ -12,6 +12,7 @@ #include "clang/AST/Comment.h" #include "clang/AST/CommentVisitor.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceManager.h" #include "clang/Format/Format.h" #include "clang/Index/USRGeneration.h" @@ -1052,6 +1053,11 @@ void CommentASTToXMLConverter::visitFullComment(const FullComment *C) { } if (AA->getUnavailable()) Result << ""; + + IdentifierInfo *Environment = AA->getEnvironment(); + if (Environment) { + Result << "" << Environment->getName() << ""; + } Result << ""; } } diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index 9c0cbea5052cb23dcb781c8d3ac72653506f1daf..3df0391bdda772f9d12674927f0f8f5023d2a411 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -1520,7 +1520,8 @@ bool NumericLiteralParser::GetIntegerValue(llvm::APInt &Val) { } llvm::APFloat::opStatus -NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) { +NumericLiteralParser::GetFloatValue(llvm::APFloat &Result, + llvm::RoundingMode RM) { using llvm::APFloat; unsigned n = std::min(SuffixBegin - ThisTokBegin, ThisTokEnd - ThisTokBegin); @@ -1534,8 +1535,7 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) { Str = Buffer; } - auto StatusOrErr = - Result.convertFromString(Str, APFloat::rmNearestTiesToEven); + auto StatusOrErr = Result.convertFromString(Str, RM); assert(StatusOrErr && "Invalid floating point representation"); return !errorToBool(StatusOrErr.takeError()) ? *StatusOrErr : APFloat::opInvalidOp; diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp index 2ca2122ac71099bf3e9903353878ccff48a6214b..8221db46e06acc1f04361bf29a08e63bafca9037 100644 --- a/clang/lib/Lex/PPLexerChange.cpp +++ b/clang/lib/Lex/PPLexerChange.cpp @@ -804,7 +804,7 @@ Module *Preprocessor::LeaveSubmodule(bool ForPragma) { llvm::SmallPtrSet VisitedMacros; for (unsigned I = Info.OuterPendingModuleMacroNames; I != PendingModuleMacroNames.size(); ++I) { - const auto *II = PendingModuleMacroNames[I]; + auto *II = PendingModuleMacroNames[I]; if (!VisitedMacros.insert(II).second) continue; diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index a478e0badb0c7cf5a78735639dc9bb12e0764ed5..8af4a97d00cb8285e4f1fce23ed8818415acec39 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -129,7 +129,7 @@ void Preprocessor::setLoadedMacroDirective(IdentifierInfo *II, II->setHasMacroDefinition(false); } -ModuleMacro *Preprocessor::addModuleMacro(Module *Mod, const IdentifierInfo *II, +ModuleMacro *Preprocessor::addModuleMacro(Module *Mod, IdentifierInfo *II, MacroInfo *Macro, ArrayRef Overrides, bool &New) { @@ -162,7 +162,7 @@ ModuleMacro *Preprocessor::addModuleMacro(Module *Mod, const IdentifierInfo *II, // The new macro is always a leaf macro. LeafMacros.push_back(MM); // The identifier now has defined macros (that may or may not be visible). - const_cast(II)->setHasMacroDefinition(true); + II->setHasMacroDefinition(true); New = true; return MM; diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index a26568dfd6aae39f7c6546714c3c16ac2e6554f6..943ce0fdde3a38a4c43e13a1648ce5affb1a437b 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -466,14 +466,14 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { ConsumeAnyToken(); } else if (HasUnparsed) { assert(Param->hasInheritedDefaultArg()); - const FunctionDecl *Old; + FunctionDecl *Old; if (const auto *FunTmpl = dyn_cast(LM.Method)) Old = cast(FunTmpl->getTemplatedDecl())->getPreviousDecl(); else Old = cast(LM.Method)->getPreviousDecl(); if (Old) { - ParmVarDecl *OldParam = const_cast(Old->getParamDecl(I)); + ParmVarDecl *OldParam = Old->getParamDecl(I); assert(!OldParam->hasUnparsedDefaultArg()); if (OldParam->hasUninstantiatedDefaultArg()) Param->setUninstantiatedDefaultArg( diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 6d026878d3276e5833ef3473649223372d34197a..445d3fd66e38792f670e9046f479209282316426 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -27,6 +27,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaCUDA.h" +#include "clang/Sema/SemaCodeCompletion.h" #include "clang/Sema/SemaDiagnostic.h" #include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" @@ -218,7 +219,8 @@ void Parser::ParseGNUAttributes(ParsedAttributes &Attrs, break; if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteAttribute(AttributeCommonInfo::Syntax::AS_GNU); + Actions.CodeCompletion().CodeCompleteAttribute( + AttributeCommonInfo::Syntax::AS_GNU); break; } IdentifierInfo *AttrName = Tok.getIdentifierInfo(); @@ -895,7 +897,8 @@ void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteAttribute(AttributeCommonInfo::AS_Declspec); + Actions.CodeCompletion().CodeCompleteAttribute( + AttributeCommonInfo::AS_Declspec); return; } @@ -1253,6 +1256,7 @@ void Parser::ParseAvailabilityAttribute( enum { Introduced, Deprecated, Obsoleted, Unknown }; AvailabilityChange Changes[Unknown]; ExprResult MessageExpr, ReplacementExpr; + IdentifierLoc *EnvironmentLoc = nullptr; // Opening '('. BalancedDelimiterTracker T(*this, tok::l_paren); @@ -1300,6 +1304,7 @@ void Parser::ParseAvailabilityAttribute( Ident_message = PP.getIdentifierInfo("message"); Ident_strict = PP.getIdentifierInfo("strict"); Ident_replacement = PP.getIdentifierInfo("replacement"); + Ident_environment = PP.getIdentifierInfo("environment"); } // Parse the optional "strict", the optional "replacement" and the set of @@ -1347,6 +1352,13 @@ void Parser::ParseAvailabilityAttribute( continue; } + if (Keyword == Ident_environment) { + if (EnvironmentLoc != nullptr) { + Diag(KeywordLoc, diag::err_availability_redundant) + << Keyword << SourceRange(EnvironmentLoc->Loc); + } + } + if (Tok.isNot(tok::equal)) { Diag(Tok, diag::err_expected_after) << Keyword << tok::equal; SkipUntil(tok::r_paren, StopAtSemi); @@ -1368,6 +1380,15 @@ void Parser::ParseAvailabilityAttribute( continue; } } + if (Keyword == Ident_environment) { + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_availability_expected_environment); + SkipUntil(tok::r_paren, StopAtSemi); + return; + } + EnvironmentLoc = ParseIdentifierLoc(); + continue; + } // Special handling of 'NA' only when applied to introduced or // deprecated. @@ -1449,7 +1470,7 @@ void Parser::ParseAvailabilityAttribute( SourceRange(AvailabilityLoc, T.getCloseLocation()), ScopeName, ScopeLoc, Platform, Changes[Introduced], Changes[Deprecated], Changes[Obsoleted], UnavailableLoc, MessageExpr.get(), Form, - StrictLoc, ReplacementExpr.get()); + StrictLoc, ReplacementExpr.get(), EnvironmentLoc); } /// Parse the contents of the "external_source_symbol" attribute. @@ -2286,7 +2307,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // Check to see if we have a function *definition* which must have a body. if (Tok.is(tok::equal) && NextToken().is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteAfterFunctionEquals(D); + Actions.CodeCompletion().CodeCompleteAfterFunctionEquals(D); return nullptr; } // We're at the point where the parsing of function declarator is finished. @@ -2722,7 +2743,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteInitializer(getCurScope(), ThisDecl); + Actions.CodeCompletion().CodeCompleteInitializer(getCurScope(), + ThisDecl); Actions.FinalizeDeclaration(ThisDecl); return nullptr; } @@ -2767,10 +2789,11 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( auto ThisVarDecl = dyn_cast_or_null(ThisDecl); auto RunSignatureHelp = [&]() { - QualType PreferredType = Actions.ProduceConstructorSignatureHelp( - ThisVarDecl->getType()->getCanonicalTypeInternal(), - ThisDecl->getLocation(), Exprs, T.getOpenLocation(), - /*Braced=*/false); + QualType PreferredType = + Actions.CodeCompletion().ProduceConstructorSignatureHelp( + ThisVarDecl->getType()->getCanonicalTypeInternal(), + ThisDecl->getLocation(), Exprs, T.getOpenLocation(), + /*Braced=*/false); CalledSignatureHelp = true; return PreferredType; }; @@ -2791,7 +2814,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( if (SawError) { if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) { - Actions.ProduceConstructorSignatureHelp( + Actions.CodeCompletion().ProduceConstructorSignatureHelp( ThisVarDecl->getType()->getCanonicalTypeInternal(), ThisDecl->getLocation(), Exprs, T.getOpenLocation(), /*Braced=*/false); @@ -2845,10 +2868,11 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( void Parser::ParseSpecifierQualifierList( DeclSpec &DS, ImplicitTypenameContext AllowImplicitTypename, AccessSpecifier AS, DeclSpecContext DSC) { + ParsedTemplateInfo TemplateInfo; /// specifier-qualifier-list is a subset of declaration-specifiers. Just /// parse declaration-specifiers and complain about extra stuff. /// TODO: diagnose attribute-specifiers and alignment-specifiers. - ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC, nullptr, + ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC, nullptr, AllowImplicitTypename); // Validate declspec for type-name. @@ -2927,7 +2951,7 @@ static bool isValidAfterIdentifierInDeclarator(const Token &T) { /// other pieces of declspec after it, it returns true. /// bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, - const ParsedTemplateInfo &TemplateInfo, + ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, DeclSpecContext DSC, ParsedAttributes &Attrs) { assert(Tok.is(tok::identifier) && "should have identifier"); @@ -3489,7 +3513,7 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, /// 'friend': [C++ dcl.friend] /// 'constexpr': [C++0x dcl.constexpr] void Parser::ParseDeclarationSpecifiers( - DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, + DeclSpec &DS, ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, DeclSpecContext DSContext, LateParsedAttrList *LateAttrs, ImplicitTypenameContext AllowImplicitTypename) { if (DS.getSourceRange().isInvalid()) { @@ -3634,7 +3658,8 @@ void Parser::ParseDeclarationSpecifiers( continue; case tok::code_completion: { - Sema::ParserCompletionContext CCC = Sema::PCC_Namespace; + SemaCodeCompletion::ParserCompletionContext CCC = + SemaCodeCompletion::PCC_Namespace; if (DS.hasTypeSpecifier()) { bool AllowNonIdentifiers = (getCurScope()->getFlags() & (Scope::ControlScope | @@ -3647,25 +3672,25 @@ void Parser::ParseDeclarationSpecifiers( (DSContext == DeclSpecContext::DSC_class && DS.isFriendSpecified()); cutOffParsing(); - Actions.CodeCompleteDeclSpec(getCurScope(), DS, - AllowNonIdentifiers, - AllowNestedNameSpecifiers); + Actions.CodeCompletion().CodeCompleteDeclSpec( + getCurScope(), DS, AllowNonIdentifiers, AllowNestedNameSpecifiers); return; } // Class context can appear inside a function/block, so prioritise that. if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) - CCC = DSContext == DeclSpecContext::DSC_class ? Sema::PCC_MemberTemplate - : Sema::PCC_Template; + CCC = DSContext == DeclSpecContext::DSC_class + ? SemaCodeCompletion::PCC_MemberTemplate + : SemaCodeCompletion::PCC_Template; else if (DSContext == DeclSpecContext::DSC_class) - CCC = Sema::PCC_Class; + CCC = SemaCodeCompletion::PCC_Class; else if (getCurScope()->getFnParent() || getCurScope()->getBlockParent()) - CCC = Sema::PCC_LocalDeclarationSpecifiers; + CCC = SemaCodeCompletion::PCC_LocalDeclarationSpecifiers; else if (CurParsedObjCImpl) - CCC = Sema::PCC_ObjCImplementation; + CCC = SemaCodeCompletion::PCC_ObjCImplementation; cutOffParsing(); - Actions.CodeCompleteOrdinaryName(getCurScope(), CCC); + Actions.CodeCompletion().CodeCompleteOrdinaryName(getCurScope(), CCC); return; } @@ -5075,7 +5100,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, if (Tok.is(tok::code_completion)) { // Code completion for an enum name. cutOffParsing(); - Actions.CodeCompleteTag(getCurScope(), DeclSpec::TST_enum); + Actions.CodeCompletion().CodeCompleteTag(getCurScope(), DeclSpec::TST_enum); DS.SetTypeSpecError(); // Needed by ActOnUsingDeclaration. return; } @@ -6265,7 +6290,7 @@ void Parser::ParseTypeQualifierListOpt( if (CodeCompletionHandler) (*CodeCompletionHandler)(); else - Actions.CodeCompleteTypeQualifiers(DS); + Actions.CodeCompletion().CodeCompleteTypeQualifiers(DS); return; case tok::kw_const: @@ -7402,12 +7427,12 @@ void Parser::ParseFunctionDeclarator(Declarator &D, // with the pure-specifier in the same way. // Parse cv-qualifier-seq[opt]. - ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, - /*AtomicAllowed*/ false, - /*IdentifierRequired=*/false, - llvm::function_ref([&]() { - Actions.CodeCompleteFunctionQualifiers(DS, D); - })); + ParseTypeQualifierListOpt( + DS, AR_NoAttributesParsed, + /*AtomicAllowed*/ false, + /*IdentifierRequired=*/false, llvm::function_ref([&]() { + Actions.CodeCompletion().CodeCompleteFunctionQualifiers(DS, D); + })); if (!DS.getSourceRange().getEnd().isInvalid()) { EndLoc = DS.getSourceRange().getEnd(); } @@ -7736,8 +7761,9 @@ void Parser::ParseParameterDeclarationClause( Diag(ThisLoc, diag::err_requires_expr_explicit_object_parameter); } - ParseDeclarationSpecifiers(DS, /*TemplateInfo=*/ParsedTemplateInfo(), - AS_none, DeclSpecContext::DSC_normal, + ParsedTemplateInfo TemplateInfo; + ParseDeclarationSpecifiers(DS, TemplateInfo, AS_none, + DeclSpecContext::DSC_normal, /*LateAttrs=*/nullptr, AllowImplicitTypename); DS.takeAttributesFrom(ArgDeclSpecAttrs); @@ -7969,7 +7995,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { return; } else if (Tok.getKind() == tok::code_completion) { cutOffParsing(); - Actions.CodeCompleteBracketDeclarator(getCurScope()); + Actions.CodeCompletion().CodeCompleteBracketDeclarator(getCurScope()); return; } diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 65ddebca49bc6d3780bbd6b04430c57dfe4e0cb1..5eaec2b621e6fd6e51061dc41f701d731a4afcd1 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -27,6 +27,7 @@ #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaCodeCompletion.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/TimeProfiler.h" #include @@ -69,7 +70,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteNamespaceDecl(getCurScope()); + Actions.CodeCompletion().CodeCompleteNamespaceDecl(getCurScope()); return nullptr; } @@ -309,7 +310,7 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteNamespaceAliasDecl(getCurScope()); + Actions.CodeCompletion().CodeCompleteNamespaceAliasDecl(getCurScope()); return nullptr; } @@ -492,7 +493,7 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDirectiveOrDeclaration( if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteUsing(getCurScope()); + Actions.CodeCompletion().CodeCompleteUsing(getCurScope()); return nullptr; } @@ -542,7 +543,7 @@ Decl *Parser::ParseUsingDirective(DeclaratorContext Context, if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteUsingDirective(getCurScope()); + Actions.CodeCompletion().CodeCompleteUsingDirective(getCurScope()); return nullptr; } @@ -733,7 +734,7 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration( if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteUsing(getCurScope()); + Actions.CodeCompletion().CodeCompleteUsing(getCurScope()); return nullptr; } @@ -1661,7 +1662,7 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { /// 'union' void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation StartLoc, DeclSpec &DS, - const ParsedTemplateInfo &TemplateInfo, + ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, bool EnteringContext, DeclSpecContext DSC, ParsedAttributes &Attributes) { @@ -1680,7 +1681,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (Tok.is(tok::code_completion)) { // Code completion for a struct, class, or union name. cutOffParsing(); - Actions.CodeCompleteTag(getCurScope(), TagType); + Actions.CodeCompletion().CodeCompleteTag(getCurScope(), TagType); return; } @@ -1861,18 +1862,14 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateParams->pop_back(); } else { TemplateParams = nullptr; - const_cast(TemplateInfo).Kind = - ParsedTemplateInfo::NonTemplate; + TemplateInfo.Kind = ParsedTemplateInfo::NonTemplate; } } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { // Pretend this is just a forward declaration. TemplateParams = nullptr; - const_cast(TemplateInfo).Kind = - ParsedTemplateInfo::NonTemplate; - const_cast(TemplateInfo).TemplateLoc = - SourceLocation(); - const_cast(TemplateInfo).ExternLoc = - SourceLocation(); + TemplateInfo.Kind = ParsedTemplateInfo::NonTemplate; + TemplateInfo.TemplateLoc = SourceLocation(); + TemplateInfo.ExternLoc = SourceLocation(); } }; @@ -1883,6 +1880,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (Tok.is(tok::identifier)) { Name = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); + DS.SetRangeEnd(NameLoc); if (Tok.is(tok::less) && getLangOpts().CPlusPlus) { // The name was supposed to refer to a template, but didn't. @@ -2722,7 +2720,7 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( ParseTypeQualifierListOpt( DS, AR_NoAttributesParsed, false, /*IdentifierRequired=*/false, llvm::function_ref([&]() { - Actions.CodeCompleteFunctionQualifiers(DS, D, &VS); + Actions.CodeCompletion().CodeCompleteFunctionQualifiers(DS, D, &VS); })); D.ExtendWithDeclSpec(DS); @@ -2803,11 +2801,9 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( /// constant-initializer: /// '=' constant-expression /// -Parser::DeclGroupPtrTy -Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, - ParsedAttributes &AccessAttrs, - const ParsedTemplateInfo &TemplateInfo, - ParsingDeclRAIIObject *TemplateDiags) { +Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration( + AccessSpecifier AS, ParsedAttributes &AccessAttrs, + ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject *TemplateDiags) { assert(getLangOpts().CPlusPlus && "ParseCXXClassMemberDeclaration should only be called in C++ mode"); if (Tok.is(tok::at)) { @@ -3085,7 +3081,8 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DefinitionKind = FunctionDefinitionKind::Deleted; else if (KW.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteAfterFunctionEquals(DeclaratorInfo); + Actions.CodeCompletion().CodeCompleteAfterFunctionEquals( + DeclaratorInfo); return nullptr; } } @@ -3524,8 +3521,10 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( case tok::kw_private: // FIXME: We don't accept GNU attributes on access specifiers in OpenCL mode // yet. - if (getLangOpts().OpenCL && !NextToken().is(tok::colon)) - return ParseCXXClassMemberDeclaration(AS, AccessAttrs); + if (getLangOpts().OpenCL && !NextToken().is(tok::colon)) { + ParsedTemplateInfo TemplateInfo; + return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo); + } [[fallthrough]]; case tok::kw_public: case tok::kw_protected: { @@ -3581,7 +3580,8 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( ConsumeAnnotationToken(); return nullptr; } - return ParseCXXClassMemberDeclaration(AS, AccessAttrs); + ParsedTemplateInfo TemplateInfo; + return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo); } } @@ -3894,8 +3894,8 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { do { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteConstructorInitializer(ConstructorDecl, - MemInitializers); + Actions.CodeCompletion().CodeCompleteConstructorInitializer( + ConstructorDecl, MemInitializers); return; } @@ -4015,9 +4015,10 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { auto RunSignatureHelp = [&] { if (TemplateTypeTy.isInvalid()) return QualType(); - QualType PreferredType = Actions.ProduceCtorInitMemberSignatureHelp( - ConstructorDecl, SS, TemplateTypeTy.get(), ArgExprs, II, - T.getOpenLocation(), /*Braced=*/false); + QualType PreferredType = + Actions.CodeCompletion().ProduceCtorInitMemberSignatureHelp( + ConstructorDecl, SS, TemplateTypeTy.get(), ArgExprs, II, + T.getOpenLocation(), /*Braced=*/false); CalledSignatureHelp = true; return PreferredType; }; @@ -4402,10 +4403,9 @@ void Parser::PopParsingClass(Sema::ParsingClassState state) { /// If a keyword or an alternative token that satisfies the syntactic /// requirements of an identifier is contained in an attribute-token, /// it is considered an identifier. -IdentifierInfo * -Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc, - Sema::AttributeCompletion Completion, - const IdentifierInfo *Scope) { +IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier( + SourceLocation &Loc, SemaCodeCompletion::AttributeCompletion Completion, + const IdentifierInfo *Scope) { switch (Tok.getKind()) { default: // Identifiers and keywords have identifier info attached. @@ -4419,9 +4419,9 @@ Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc, case tok::code_completion: cutOffParsing(); - Actions.CodeCompleteAttribute(getLangOpts().CPlusPlus ? ParsedAttr::AS_CXX11 - : ParsedAttr::AS_C23, - Completion, Scope); + Actions.CodeCompletion().CodeCompleteAttribute( + getLangOpts().CPlusPlus ? ParsedAttr::AS_CXX11 : ParsedAttr::AS_C23, + Completion, Scope); return nullptr; case tok::numeric_constant: { @@ -4804,7 +4804,7 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs, ConsumeToken(); CommonScopeName = TryParseCXX11AttributeIdentifier( - CommonScopeLoc, Sema::AttributeCompletion::Scope); + CommonScopeLoc, SemaCodeCompletion::AttributeCompletion::Scope); if (!CommonScopeName) { Diag(Tok.getLocation(), diag::err_expected) << tok::identifier; SkipUntil(tok::r_square, tok::colon, StopBeforeMatch); @@ -4833,7 +4833,8 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs, IdentifierInfo *ScopeName = nullptr, *AttrName = nullptr; AttrName = TryParseCXX11AttributeIdentifier( - AttrLoc, Sema::AttributeCompletion::Attribute, CommonScopeName); + AttrLoc, SemaCodeCompletion::AttributeCompletion::Attribute, + CommonScopeName); if (!AttrName) // Break out to the "expected ']'" diagnostic. break; @@ -4844,7 +4845,8 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs, ScopeLoc = AttrLoc; AttrName = TryParseCXX11AttributeIdentifier( - AttrLoc, Sema::AttributeCompletion::Attribute, ScopeName); + AttrLoc, SemaCodeCompletion::AttributeCompletion::Attribute, + ScopeName); if (!AttrName) { Diag(Tok.getLocation(), diag::err_expected) << tok::identifier; SkipUntil(tok::r_square, tok::comma, StopAtSemi | StopBeforeMatch); @@ -5068,9 +5070,10 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &Attrs) { StopAtSemi | StopBeforeMatch | StopAtCodeCompletion); if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteAttribute(AttributeCommonInfo::AS_Microsoft, - Sema::AttributeCompletion::Attribute, - /*Scope=*/nullptr); + Actions.CodeCompletion().CodeCompleteAttribute( + AttributeCommonInfo::AS_Microsoft, + SemaCodeCompletion::AttributeCompletion::Attribute, + /*Scope=*/nullptr); break; } if (Tok.isNot(tok::identifier)) // ']', but also eof @@ -5166,8 +5169,9 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration( continue; } + ParsedTemplateInfo TemplateInfo; // Parse all the comma separated declarators. - ParseCXXClassMemberDeclaration(CurAS, AccessAttrs); + ParseCXXClassMemberDeclaration(CurAS, AccessAttrs, TemplateInfo); } Braces.consumeClose(); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 9cd7d20fc4d584879026d01370ea33819cb3fe20..eb7447fa038e479346029febd580d16b07e40eb2 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -31,6 +31,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaCUDA.h" +#include "clang/Sema/SemaCodeCompletion.h" #include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenACC.h" #include "clang/Sema/SemaOpenMP.h" @@ -168,8 +169,8 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) { ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteExpression(getCurScope(), - PreferredType.get(Tok.getLocation())); + Actions.CodeCompletion().CodeCompleteExpression( + getCurScope(), PreferredType.get(Tok.getLocation())); return ExprError(); } @@ -187,8 +188,8 @@ ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) { ExprResult Parser::ParseConditionalExpression() { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteExpression(getCurScope(), - PreferredType.get(Tok.getLocation())); + Actions.CodeCompletion().CodeCompleteExpression( + getCurScope(), PreferredType.get(Tok.getLocation())); return ExprError(); } @@ -1215,7 +1216,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, if (Tok.is(tok::code_completion) && &II != Ident_super) { cutOffParsing(); - Actions.CodeCompleteObjCClassPropertyRefExpr( + Actions.CodeCompletion().CodeCompleteObjCClassPropertyRefExpr( getCurScope(), II, ILoc, ExprStatementTokLoc == ILoc); return ExprError(); } @@ -1811,8 +1812,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, break; case tok::code_completion: { cutOffParsing(); - Actions.CodeCompleteExpression(getCurScope(), - PreferredType.get(Tok.getLocation())); + Actions.CodeCompletion().CodeCompleteExpression( + getCurScope(), PreferredType.get(Tok.getLocation())); return ExprError(); } #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: @@ -1956,7 +1957,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { return LHS; cutOffParsing(); - Actions.CodeCompletePostfixExpression( + Actions.CodeCompletion().CodeCompletePostfixExpression( getCurScope(), LHS, PreferredType.get(Tok.getLocation())); return ExprError(); @@ -2154,8 +2155,9 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { ExprVector ArgExprs; auto RunSignatureHelp = [&]() -> QualType { - QualType PreferredType = Actions.ProduceCallSignatureHelp( - LHS.get(), ArgExprs, PT.getOpenLocation()); + QualType PreferredType = + Actions.CodeCompletion().ProduceCallSignatureHelp( + LHS.get(), ArgExprs, PT.getOpenLocation()); CalledSignatureHelp = true; return PreferredType; }; @@ -2279,7 +2281,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { // Code completion for a member access expression. cutOffParsing(); - Actions.CodeCompleteMemberReferenceExpr( + Actions.CodeCompletion().CodeCompleteMemberReferenceExpr( getCurScope(), Base, CorrectedBase, OpLoc, OpKind == tok::arrow, Base && ExprStatementTokLoc == Base->getBeginLoc(), PreferredType.get(Tok.getLocation())); @@ -3001,7 +3003,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteExpression( + Actions.CodeCompletion().CodeCompleteExpression( getCurScope(), PreferredType.get(Tok.getLocation()), /*IsParenthesized=*/ExprType >= CompoundLiteral); return ExprError(); @@ -3678,7 +3680,8 @@ bool Parser::ParseSimpleExpressionList(SmallVectorImpl &Exprs) { void Parser::ParseBlockId(SourceLocation CaretLoc) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type); + Actions.CodeCompletion().CodeCompleteOrdinaryName( + getCurScope(), SemaCodeCompletion::PCC_Type); return; } @@ -3867,7 +3870,7 @@ std::optional Parser::ParseAvailabilitySpec() { // Parse the platform name. if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteAvailabilityPlatformName(); + Actions.CodeCompletion().CodeCompleteAvailabilityPlatformName(); return std::nullopt; } if (Tok.isNot(tok::identifier)) { diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 825031da358ad57909e209209c76c5c679abb4e0..e149b1a0fb5efc94ce61ef7802af9332c28c7b17 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -23,6 +23,7 @@ #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaCodeCompletion.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include @@ -270,9 +271,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier( cutOffParsing(); // Code completion for a nested-name-specifier, where the code // completion token follows the '::'. - Actions.CodeCompleteQualifiedId(getCurScope(), SS, EnteringContext, - InUsingDeclaration, ObjectType.get(), - SavedType.get(SS.getBeginLoc())); + Actions.CodeCompletion().CodeCompleteQualifiedId( + getCurScope(), SS, EnteringContext, InUsingDeclaration, + ObjectType.get(), SavedType.get(SS.getBeginLoc())); // Include code completion token into the range of the scope otherwise // when we try to annotate the scope tokens the dangling code completion // token will cause assertion in @@ -954,8 +955,9 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, if (Tok.is(tok::code_completion) && !(getLangOpts().ObjC && Tentative)) { cutOffParsing(); - Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro, - /*AfterAmpersand=*/false); + Actions.CodeCompletion().CodeCompleteLambdaIntroducer( + getCurScope(), Intro, + /*AfterAmpersand=*/false); break; } @@ -971,10 +973,11 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // If we're in Objective-C++ and we have a bare '[', then this is more // likely to be a message receiver. if (getLangOpts().ObjC && Tentative && First) - Actions.CodeCompleteObjCMessageReceiver(getCurScope()); + Actions.CodeCompletion().CodeCompleteObjCMessageReceiver(getCurScope()); else - Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro, - /*AfterAmpersand=*/false); + Actions.CodeCompletion().CodeCompleteLambdaIntroducer( + getCurScope(), Intro, + /*AfterAmpersand=*/false); break; } @@ -1020,8 +1023,9 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro, - /*AfterAmpersand=*/true); + Actions.CodeCompletion().CodeCompleteLambdaIntroducer( + getCurScope(), Intro, + /*AfterAmpersand=*/true); break; } } @@ -2031,9 +2035,10 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { auto RunSignatureHelp = [&]() { QualType PreferredType; if (TypeRep) - PreferredType = Actions.ProduceConstructorSignatureHelp( - TypeRep.get()->getCanonicalTypeInternal(), DS.getEndLoc(), Exprs, - T.getOpenLocation(), /*Braced=*/false); + PreferredType = + Actions.CodeCompletion().ProduceConstructorSignatureHelp( + TypeRep.get()->getCanonicalTypeInternal(), DS.getEndLoc(), + Exprs, T.getOpenLocation(), /*Braced=*/false); CalledSignatureHelp = true; return PreferredType; }; @@ -2140,7 +2145,8 @@ Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc, if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Condition); + Actions.CodeCompletion().CodeCompleteOrdinaryName( + getCurScope(), SemaCodeCompletion::PCC_Condition); return Sema::ConditionError(); } @@ -2792,7 +2798,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // Don't try to parse any further. cutOffParsing(); // Code completion for the operator name. - Actions.CodeCompleteOperatorName(getCurScope()); + Actions.CodeCompletion().CodeCompleteOperatorName(getCurScope()); return true; } @@ -3350,10 +3356,12 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { // the passing DeclaratorInfo is valid, e.g. running SignatureHelp on // `new decltype(invalid) (^)`. if (TypeRep) - PreferredType = Actions.ProduceConstructorSignatureHelp( - TypeRep.get()->getCanonicalTypeInternal(), - DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen, - /*Braced=*/false); + PreferredType = + Actions.CodeCompletion().ProduceConstructorSignatureHelp( + TypeRep.get()->getCanonicalTypeInternal(), + DeclaratorInfo.getEndLoc(), ConstructorArgs, + ConstructorLParen, + /*Braced=*/false); CalledSignatureHelp = true; return PreferredType; }; diff --git a/clang/lib/Parse/ParseInit.cpp b/clang/lib/Parse/ParseInit.cpp index 04e4419f4d459417df35f3ffc5bb478473eaad86..432ddc74b1087b9f3cb69d09472e787ecaa6414c 100644 --- a/clang/lib/Parse/ParseInit.cpp +++ b/clang/lib/Parse/ParseInit.cpp @@ -18,6 +18,7 @@ #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Ownership.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaCodeCompletion.h" #include "clang/Sema/SemaObjC.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" @@ -204,8 +205,9 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator( if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteDesignator(DesignatorCompletion.PreferredBaseType, - DesignatorCompletion.InitExprs, Desig); + Actions.CodeCompletion().CodeCompleteDesignator( + DesignatorCompletion.PreferredBaseType, + DesignatorCompletion.InitExprs, Desig); return ExprError(); } if (Tok.isNot(tok::identifier)) { @@ -471,7 +473,7 @@ ExprResult Parser::ParseBraceInitializer() { auto RunSignatureHelp = [&] { QualType PreferredType; if (!LikelyType.isNull()) - PreferredType = Actions.ProduceConstructorSignatureHelp( + PreferredType = Actions.CodeCompletion().ProduceConstructorSignatureHelp( LikelyType->getCanonicalTypeInternal(), T.getOpenLocation(), InitExprs, T.getOpenLocation(), /*Braced=*/true); CalledSignatureHelp = true; diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 4cb04b3534738c1f69553d247f496e73a83ee37c..89f4acbd25e4936066853cefb2cc511eae306552 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -20,6 +20,7 @@ #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaCodeCompletion.h" #include "clang/Sema/SemaObjC.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" @@ -56,7 +57,7 @@ Parser::ParseObjCAtDirectives(ParsedAttributes &DeclAttrs, if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCAtDirective(getCurScope()); + Actions.CodeCompletion().CodeCompleteObjCAtDirective(getCurScope()); return nullptr; } @@ -156,7 +157,7 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { MaybeSkipAttributes(tok::objc_class); if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCClassForwardDecl(getCurScope()); + Actions.CodeCompletion().CodeCompleteObjCClassForwardDecl(getCurScope()); return Actions.ConvertDeclToDeclGroup(nullptr); } if (expectIdentifier()) { @@ -242,7 +243,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, // Code completion after '@interface'. if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCInterfaceDecl(getCurScope()); + Actions.CodeCompletion().CodeCompleteObjCInterfaceDecl(getCurScope()); return nullptr; } @@ -276,7 +277,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, IdentifierInfo *categoryId = nullptr; if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc); + Actions.CodeCompletion().CodeCompleteObjCInterfaceCategory( + getCurScope(), nameId, nameLoc); return nullptr; } @@ -331,7 +333,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, // Code completion of superclass names. if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc); + Actions.CodeCompletion().CodeCompleteObjCSuperclass(getCurScope(), nameId, + nameLoc); return nullptr; } @@ -508,7 +511,8 @@ ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( // FIXME: If these aren't protocol references, we'll need different // completions. cutOffParsing(); - Actions.CodeCompleteObjCProtocolReferences(protocolIdents); + Actions.CodeCompletion().CodeCompleteObjCProtocolReferences( + protocolIdents); // FIXME: Better recovery here?. return nullptr; @@ -681,9 +685,10 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, // Code completion within an Objective-C interface. if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteOrdinaryName(getCurScope(), - CurParsedObjCImpl? Sema::PCC_ObjCImplementation - : Sema::PCC_ObjCInterface); + Actions.CodeCompletion().CodeCompleteOrdinaryName( + getCurScope(), CurParsedObjCImpl + ? SemaCodeCompletion::PCC_ObjCImplementation + : SemaCodeCompletion::PCC_ObjCInterface); return; } @@ -720,7 +725,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, const auto &NextTok = NextToken(); if (NextTok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCAtDirective(getCurScope()); + Actions.CodeCompletion().CodeCompleteObjCAtDirective(getCurScope()); return; } @@ -895,7 +900,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { while (true) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCPropertyFlags(getCurScope(), DS); + Actions.CodeCompletion().CodeCompleteObjCPropertyFlags(getCurScope(), DS); return; } const IdentifierInfo *II = Tok.getIdentifierInfo(); @@ -943,9 +948,11 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { if (Tok.is(tok::code_completion)) { cutOffParsing(); if (IsSetter) - Actions.CodeCompleteObjCPropertySetter(getCurScope()); + Actions.CodeCompletion().CodeCompleteObjCPropertySetter( + getCurScope()); else - Actions.CodeCompleteObjCPropertyGetter(getCurScope()); + Actions.CodeCompletion().CodeCompleteObjCPropertyGetter( + getCurScope()); return; } @@ -1196,7 +1203,7 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, while (true) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCPassingType( + Actions.CodeCompletion().CodeCompleteObjCPassingType( getCurScope(), DS, Context == DeclaratorContext::ObjCParameter); return; } @@ -1390,8 +1397,9 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, - /*ReturnType=*/nullptr); + Actions.CodeCompletion().CodeCompleteObjCMethodDecl(getCurScope(), + mType == tok::minus, + /*ReturnType=*/nullptr); return nullptr; } @@ -1409,8 +1417,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, - ReturnType); + Actions.CodeCompletion().CodeCompleteObjCMethodDecl( + getCurScope(), mType == tok::minus, ReturnType); return nullptr; } @@ -1472,10 +1480,9 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, if (Tok.is(tok::code_completion)) { cutOffParsing(); KeyIdents.push_back(SelIdent); - Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(), - mType == tok::minus, - /*AtParameterName=*/true, - ReturnType, KeyIdents); + Actions.CodeCompletion().CodeCompleteObjCMethodDeclSelector( + getCurScope(), mType == tok::minus, + /*AtParameterName=*/true, ReturnType, KeyIdents); return nullptr; } @@ -1496,10 +1503,9 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // Code completion for the next piece of the selector. if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(), - mType == tok::minus, - /*AtParameterName=*/false, - ReturnType, KeyIdents); + Actions.CodeCompletion().CodeCompleteObjCMethodDeclSelector( + getCurScope(), mType == tok::minus, + /*AtParameterName=*/false, ReturnType, KeyIdents); return nullptr; } @@ -1533,7 +1539,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, cStyleParamWarned = true; } DeclSpec DS(AttrFactory); - ParseDeclarationSpecifiers(DS); + ParsedTemplateInfo TemplateInfo; + ParseDeclarationSpecifiers(DS, TemplateInfo); // Parse the declarator. Declarator ParmDecl(DS, ParsedAttributesView::none(), DeclaratorContext::Prototype); @@ -1583,7 +1590,8 @@ ParseObjCProtocolReferences(SmallVectorImpl &Protocols, while (true) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents); + Actions.CodeCompletion().CodeCompleteObjCProtocolReferences( + ProtocolIdents); return true; } @@ -1681,9 +1689,11 @@ void Parser::parseObjCTypeArgsOrProtocolQualifiers( QualType BaseT = Actions.GetTypeFromParser(baseType); cutOffParsing(); if (!BaseT.isNull() && BaseT->acceptsObjCTypeParams()) { - Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type); + Actions.CodeCompletion().CodeCompleteOrdinaryName( + getCurScope(), SemaCodeCompletion::PCC_Type); } else { - Actions.CodeCompleteObjCProtocolReferences(identifierLocPairs); + Actions.CodeCompletion().CodeCompleteObjCProtocolReferences( + identifierLocPairs); } return; } @@ -1958,7 +1968,7 @@ void Parser::ParseObjCClassInstanceVariables(ObjCContainerDecl *interfaceDecl, if (TryConsumeToken(tok::at)) { // parse objc-visibility-spec if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCAtVisibility(getCurScope()); + Actions.CodeCompletion().CodeCompleteObjCAtVisibility(getCurScope()); return; } @@ -1989,8 +1999,8 @@ void Parser::ParseObjCClassInstanceVariables(ObjCContainerDecl *interfaceDecl, if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteOrdinaryName(getCurScope(), - Sema::PCC_ObjCInstanceVariableList); + Actions.CodeCompletion().CodeCompleteOrdinaryName( + getCurScope(), SemaCodeCompletion::PCC_ObjCInstanceVariableList); return; } @@ -2057,7 +2067,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCProtocolDecl(getCurScope()); + Actions.CodeCompletion().CodeCompleteObjCProtocolDecl(getCurScope()); return nullptr; } @@ -2155,7 +2165,7 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc, // Code completion after '@implementation'. if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCImplementationDecl(getCurScope()); + Actions.CodeCompletion().CodeCompleteObjCImplementationDecl(getCurScope()); return nullptr; } @@ -2193,7 +2203,8 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc, if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc); + Actions.CodeCompletion().CodeCompleteObjCImplementationCategory( + getCurScope(), nameId, nameLoc); return nullptr; } @@ -2367,7 +2378,8 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { while (true) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); + Actions.CodeCompletion().CodeCompleteObjCPropertyDefinition( + getCurScope()); return nullptr; } @@ -2385,7 +2397,8 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { // property '=' ivar-name if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId); + Actions.CodeCompletion().CodeCompleteObjCPropertySynthesizeIvar( + getCurScope(), propertyId); return nullptr; } @@ -2444,7 +2457,8 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { while (true) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); + Actions.CodeCompletion().CodeCompleteObjCPropertyDefinition( + getCurScope()); return nullptr; } @@ -2588,7 +2602,8 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { Scope::AtCatchScope); if (Tok.isNot(tok::ellipsis)) { DeclSpec DS(AttrFactory); - ParseDeclarationSpecifiers(DS); + ParsedTemplateInfo TemplateInfo; + ParseDeclarationSpecifiers(DS, TemplateInfo); Declarator ParmDecl(DS, ParsedAttributesView::none(), DeclaratorContext::ObjCCatch); ParseDeclarator(ParmDecl); @@ -2782,7 +2797,7 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc, ParsedStmtContext StmtCtx) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCAtStatement(getCurScope()); + Actions.CodeCompletion().CodeCompleteObjCAtStatement(getCurScope()); return StmtError(); } @@ -2823,7 +2838,7 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { switch (Tok.getKind()) { case tok::code_completion: cutOffParsing(); - Actions.CodeCompleteObjCAtExpression(getCurScope()); + Actions.CodeCompletion().CodeCompleteObjCAtExpression(getCurScope()); return ExprError(); case tok::minus: @@ -3071,7 +3086,7 @@ ExprResult Parser::ParseObjCMessageExpression() { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCMessageReceiver(getCurScope()); + Actions.CodeCompletion().CodeCompleteObjCMessageReceiver(getCurScope()); return ExprError(); } @@ -3208,14 +3223,14 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, if (Tok.is(tok::code_completion)) { cutOffParsing(); if (SuperLoc.isValid()) - Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, - std::nullopt, false); + Actions.CodeCompletion().CodeCompleteObjCSuperMessage( + getCurScope(), SuperLoc, std::nullopt, false); else if (ReceiverType) - Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, - std::nullopt, false); + Actions.CodeCompletion().CodeCompleteObjCClassMessage( + getCurScope(), ReceiverType, std::nullopt, false); else - Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr, - std::nullopt, false); + Actions.CodeCompletion().CodeCompleteObjCInstanceMessage( + getCurScope(), ReceiverExpr, std::nullopt, false); return ExprError(); } @@ -3246,17 +3261,17 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, if (Tok.is(tok::code_completion)) { cutOffParsing(); if (SuperLoc.isValid()) - Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, - KeyIdents, - /*AtArgumentExpression=*/true); + Actions.CodeCompletion().CodeCompleteObjCSuperMessage( + getCurScope(), SuperLoc, KeyIdents, + /*AtArgumentExpression=*/true); else if (ReceiverType) - Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, - KeyIdents, - /*AtArgumentExpression=*/true); + Actions.CodeCompletion().CodeCompleteObjCClassMessage( + getCurScope(), ReceiverType, KeyIdents, + /*AtArgumentExpression=*/true); else - Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr, - KeyIdents, - /*AtArgumentExpression=*/true); + Actions.CodeCompletion().CodeCompleteObjCInstanceMessage( + getCurScope(), ReceiverExpr, KeyIdents, + /*AtArgumentExpression=*/true); return ExprError(); } @@ -3284,17 +3299,17 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, if (Tok.is(tok::code_completion)) { cutOffParsing(); if (SuperLoc.isValid()) - Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, - KeyIdents, - /*AtArgumentExpression=*/false); + Actions.CodeCompletion().CodeCompleteObjCSuperMessage( + getCurScope(), SuperLoc, KeyIdents, + /*AtArgumentExpression=*/false); else if (ReceiverType) - Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, - KeyIdents, - /*AtArgumentExpression=*/false); + Actions.CodeCompletion().CodeCompleteObjCClassMessage( + getCurScope(), ReceiverType, KeyIdents, + /*AtArgumentExpression=*/false); else - Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr, - KeyIdents, - /*AtArgumentExpression=*/false); + Actions.CodeCompletion().CodeCompleteObjCInstanceMessage( + getCurScope(), ReceiverExpr, KeyIdents, + /*AtArgumentExpression=*/false); return ExprError(); } @@ -3635,7 +3650,7 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents); + Actions.CodeCompletion().CodeCompleteObjCSelector(getCurScope(), KeyIdents); return ExprError(); } @@ -3661,7 +3676,8 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents); + Actions.CodeCompletion().CodeCompleteObjCSelector(getCurScope(), + KeyIdents); return ExprError(); } diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index ca2c6d69eb9852d331a9c2ec1a3424bd04375e17..e959dd6378f46b21da506c67633b55d7c128b9fb 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -21,6 +21,7 @@ #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaCodeCompletion.h" #include "clang/Sema/SemaOpenMP.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/StringSwitch.h" @@ -460,7 +461,8 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm); + Actions.CodeCompletion().CodeCompleteInitializer(getCurScope(), + OmpPrivParm); Actions.FinalizeDeclaration(OmpPrivParm); return; } @@ -484,9 +486,10 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { SourceLocation LParLoc = T.getOpenLocation(); auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() { - QualType PreferredType = Actions.ProduceConstructorSignatureHelp( - OmpPrivParm->getType()->getCanonicalTypeInternal(), - OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false); + QualType PreferredType = + Actions.CodeCompletion().ProduceConstructorSignatureHelp( + OmpPrivParm->getType()->getCanonicalTypeInternal(), + OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false); CalledSignatureHelp = true; return PreferredType; }; diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index cd0fab5fe31d3fc66928ccd079d380441cbd7ee6..643fdac287d18eac5ac4e6d24753ad2d425710a1 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -22,6 +22,7 @@ #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaCUDA.h" +#include "clang/Sema/SemaCodeCompletion.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringSwitch.h" #include @@ -1924,7 +1925,8 @@ void Parser::HandlePragmaAttribute() { if (Tok.is(tok::code_completion)) { cutOffParsing(); // FIXME: suppress completion of unsupported attributes? - Actions.CodeCompleteAttribute(AttributeCommonInfo::Syntax::AS_GNU); + Actions.CodeCompletion().CodeCompleteAttribute( + AttributeCommonInfo::Syntax::AS_GNU); return SkipToEnd(); } diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index e0116d3003100847d78f6c3629e5e3ad1b2a4845..b0af04451166ca20febe0cf6c1e2b78ef0ce5750 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -22,6 +22,7 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaCodeCompletion.h" #include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" #include "clang/Sema/TypoCorrection.h" @@ -191,7 +192,8 @@ Retry: case tok::code_completion: cutOffParsing(); - Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement); + Actions.CodeCompletion().CodeCompleteOrdinaryName( + getCurScope(), SemaCodeCompletion::PCC_Statement); return StmtError(); case tok::identifier: @@ -843,7 +845,7 @@ StmtResult Parser::ParseCaseStatement(ParsedStmtContext StmtCtx, if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteCase(getCurScope()); + Actions.CodeCompletion().CodeCompleteCase(getCurScope()); return StmtError(); } @@ -1649,7 +1651,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { InnerScope.Exit(); } else if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteAfterIf(getCurScope(), IsBracedThen); + Actions.CodeCompletion().CodeCompleteAfterIf(getCurScope(), IsBracedThen); return StmtError(); } else if (InnerStatementTrailingElseLoc.isValid()) { Diag(InnerStatementTrailingElseLoc, diag::warn_dangling_else); @@ -2040,9 +2042,9 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteOrdinaryName(getCurScope(), - C99orCXXorObjC? Sema::PCC_ForInit - : Sema::PCC_Expression); + Actions.CodeCompletion().CodeCompleteOrdinaryName( + getCurScope(), C99orCXXorObjC ? SemaCodeCompletion::PCC_ForInit + : SemaCodeCompletion::PCC_Expression); return StmtError(); } @@ -2117,7 +2119,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCForCollection(getCurScope(), DG); + Actions.CodeCompletion().CodeCompleteObjCForCollection(getCurScope(), + DG); return StmtError(); } Collection = ParseExpression(); @@ -2154,7 +2157,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteObjCForCollection(getCurScope(), nullptr); + Actions.CodeCompletion().CodeCompleteObjCForCollection(getCurScope(), + nullptr); return StmtError(); } Collection = ParseExpression(); @@ -2431,8 +2435,8 @@ StmtResult Parser::ParseReturnStatement() { // FIXME: Code completion for co_return. if (Tok.is(tok::code_completion) && !IsCoreturn) { cutOffParsing(); - Actions.CodeCompleteExpression(getCurScope(), - PreferredType.get(Tok.getLocation())); + Actions.CodeCompletion().CodeCompleteExpression( + getCurScope(), PreferredType.get(Tok.getLocation())); return StmtError(); } diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 665253a6674d27add53478667a99269212ac8f02..a5130f56600e54bce685e17dbfb677fc56bff8b7 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -167,9 +167,13 @@ Parser::DeclGroupPtrTy Parser::ParseTemplateDeclarationOrSpecialization( LastParamListWasEmpty); // Parse the actual template declaration. - if (Tok.is(tok::kw_concept)) - return Actions.ConvertDeclToDeclGroup( - ParseConceptDefinition(TemplateInfo, DeclEnd)); + if (Tok.is(tok::kw_concept)) { + Decl *ConceptDecl = ParseConceptDefinition(TemplateInfo, DeclEnd); + // We need to explicitly pass ConceptDecl to ParsingDeclRAIIObject, so that + // delayed diagnostics (e.g. warn_deprecated) have a Decl to work with. + ParsingTemplateParams.complete(ConceptDecl); + return Actions.ConvertDeclToDeclGroup(ConceptDecl); + } return ParseDeclarationAfterTemplate( Context, TemplateInfo, ParsingTemplateParams, DeclEnd, AccessAttrs, AS); @@ -316,7 +320,8 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo, const IdentifierInfo *Id = Result.Identifier; SourceLocation IdLoc = Result.getBeginLoc(); - DiagnoseAndSkipCXX11Attributes(); + ParsedAttributes Attrs(AttrFactory); + MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs); if (!TryConsumeToken(tok::equal)) { Diag(Tok.getLocation(), diag::err_expected) << tok::equal; @@ -335,8 +340,8 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo, ExpectAndConsumeSemi(diag::err_expected_semi_declaration); Expr *ConstraintExpr = ConstraintExprResult.get(); return Actions.ActOnConceptDefinition(getCurScope(), - *TemplateInfo.TemplateParams, - Id, IdLoc, ConstraintExpr); + *TemplateInfo.TemplateParams, Id, IdLoc, + ConstraintExpr, Attrs); } /// ParseTemplateParameters - Parses a template-parameter-list enclosed in @@ -902,7 +907,8 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { // FIXME: The type should probably be restricted in some way... Not all // declarators (parts of declarators?) are accepted for parameters. DeclSpec DS(AttrFactory); - ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, + ParsedTemplateInfo TemplateInfo; + ParseDeclarationSpecifiers(DS, TemplateInfo, AS_none, DeclSpecContext::DSC_template_param); // Parse this as a typename. @@ -1535,8 +1541,8 @@ bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs, if (!Template) return QualType(); CalledSignatureHelp = true; - return Actions.ProduceTemplateArgumentSignatureHelp(Template, TemplateArgs, - OpenLoc); + return Actions.CodeCompletion().ProduceTemplateArgumentSignatureHelp( + Template, TemplateArgs, OpenLoc); }; do { diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 869b9c6669c27f0de5d47850e36f2904ce01e55f..6d0cf7b174e50eefb28cdf2b1c3ce3d0a46e7aaa 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -21,6 +21,7 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaCodeCompletion.h" #include "llvm/Support/Path.h" #include "llvm/Support/TimeProfiler.h" using namespace clang; @@ -944,20 +945,21 @@ Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, cutOffParsing(); if (CurParsedObjCImpl) { // Code-complete Objective-C methods even without leading '-'/'+' prefix. - Actions.CodeCompleteObjCMethodDecl(getCurScope(), - /*IsInstanceMethod=*/std::nullopt, - /*ReturnType=*/nullptr); + Actions.CodeCompletion().CodeCompleteObjCMethodDecl( + getCurScope(), + /*IsInstanceMethod=*/std::nullopt, + /*ReturnType=*/nullptr); } - Sema::ParserCompletionContext PCC; + SemaCodeCompletion::ParserCompletionContext PCC; if (CurParsedObjCImpl) { - PCC = Sema::PCC_ObjCImplementation; + PCC = SemaCodeCompletion::PCC_ObjCImplementation; } else if (PP.isIncrementalProcessingEnabled()) { - PCC = Sema::PCC_TopLevelOrExpression; + PCC = SemaCodeCompletion::PCC_TopLevelOrExpression; } else { - PCC = Sema::PCC_Namespace; + PCC = SemaCodeCompletion::PCC_Namespace; }; - Actions.CodeCompleteOrdinaryName(getCurScope(), PCC); + Actions.CodeCompletion().CodeCompleteOrdinaryName(getCurScope(), PCC); return nullptr; case tok::kw_import: { Sema::ModuleImportState IS = Sema::ModuleImportState::NotACXX20Module; @@ -1562,7 +1564,8 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { // Parse the common declaration-specifiers piece. DeclSpec DS(AttrFactory); - ParseDeclarationSpecifiers(DS); + ParsedTemplateInfo TemplateInfo; + ParseDeclarationSpecifiers(DS, TemplateInfo); // C99 6.9.1p6: 'each declaration in the declaration list shall have at // least one declarator'. @@ -2280,54 +2283,57 @@ SourceLocation Parser::handleUnexpectedCodeCompletionToken() { for (Scope *S = getCurScope(); S; S = S->getParent()) { if (S->isFunctionScope()) { cutOffParsing(); - Actions.CodeCompleteOrdinaryName(getCurScope(), - Sema::PCC_RecoveryInFunction); + Actions.CodeCompletion().CodeCompleteOrdinaryName( + getCurScope(), SemaCodeCompletion::PCC_RecoveryInFunction); return PrevTokLocation; } if (S->isClassScope()) { cutOffParsing(); - Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Class); + Actions.CodeCompletion().CodeCompleteOrdinaryName( + getCurScope(), SemaCodeCompletion::PCC_Class); return PrevTokLocation; } } cutOffParsing(); - Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Namespace); + Actions.CodeCompletion().CodeCompleteOrdinaryName( + getCurScope(), SemaCodeCompletion::PCC_Namespace); return PrevTokLocation; } // Code-completion pass-through functions void Parser::CodeCompleteDirective(bool InConditional) { - Actions.CodeCompletePreprocessorDirective(InConditional); + Actions.CodeCompletion().CodeCompletePreprocessorDirective(InConditional); } void Parser::CodeCompleteInConditionalExclusion() { - Actions.CodeCompleteInPreprocessorConditionalExclusion(getCurScope()); + Actions.CodeCompletion().CodeCompleteInPreprocessorConditionalExclusion( + getCurScope()); } void Parser::CodeCompleteMacroName(bool IsDefinition) { - Actions.CodeCompletePreprocessorMacroName(IsDefinition); + Actions.CodeCompletion().CodeCompletePreprocessorMacroName(IsDefinition); } void Parser::CodeCompletePreprocessorExpression() { - Actions.CodeCompletePreprocessorExpression(); + Actions.CodeCompletion().CodeCompletePreprocessorExpression(); } void Parser::CodeCompleteMacroArgument(IdentifierInfo *Macro, MacroInfo *MacroInfo, unsigned ArgumentIndex) { - Actions.CodeCompletePreprocessorMacroArgument(getCurScope(), Macro, MacroInfo, - ArgumentIndex); + Actions.CodeCompletion().CodeCompletePreprocessorMacroArgument( + getCurScope(), Macro, MacroInfo, ArgumentIndex); } void Parser::CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled) { - Actions.CodeCompleteIncludedFile(Dir, IsAngled); + Actions.CodeCompletion().CodeCompleteIncludedFile(Dir, IsAngled); } void Parser::CodeCompleteNaturalLanguage() { - Actions.CodeCompleteNaturalLanguage(); + Actions.CodeCompletion().CodeCompleteNaturalLanguage(); } bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) { @@ -2681,7 +2687,7 @@ bool Parser::ParseModuleName( if (!Tok.is(tok::identifier)) { if (Tok.is(tok::code_completion)) { cutOffParsing(); - Actions.CodeCompleteModuleImport(UseLoc, Path); + Actions.CodeCompletion().CodeCompleteModuleImport(UseLoc, Path); return true; } diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 6992ba9ad9a7564ee9c2325f610fcb29ff2fa8fc..b9d0b59ef1db7373bf04c0f05e1559d72d3e40d0 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2256,11 +2256,8 @@ public: Range = UO->getSubExpr()->getSourceRange(); MsgParam = 1; } - } else if (const auto *CtorExpr = dyn_cast(Operation)) { - S.Diag(CtorExpr->getLocation(), - diag::warn_unsafe_buffer_usage_in_container); } else { - if (isa(Operation)) { + if (isa(Operation) || isa(Operation)) { // note_unsafe_buffer_operation doesn't have this mode yet. assert(!IsRelatedToDecl && "Not implemented yet!"); MsgParam = 3; @@ -2295,6 +2292,26 @@ public: } } + void handleUnsafeOperationInContainer(const Stmt *Operation, + bool IsRelatedToDecl, + ASTContext &Ctx) override { + SourceLocation Loc; + SourceRange Range; + unsigned MsgParam = 0; + + // This function only handles SpanTwoParamConstructorGadget so far, which + // always gives a CXXConstructExpr. + const auto *CtorExpr = cast(Operation); + Loc = CtorExpr->getLocation(); + + S.Diag(Loc, diag::warn_unsafe_buffer_usage_in_container); + if (IsRelatedToDecl) { + assert(!SuggestSuggestions && + "Variables blamed for unsafe buffer usage without suggestions!"); + S.Diag(Loc, diag::note_unsafe_buffer_operation) << MsgParam << Range; + } + } + void handleUnsafeVariableGroup(const VarDecl *Variable, const VariableGroupsManager &VarGrpMgr, FixItList &&Fixes, const Decl *D, diff --git a/clang/lib/Sema/OpenCLBuiltins.td b/clang/lib/Sema/OpenCLBuiltins.td index a7bdfe20b98280d239fa2bf8b8b418a9a79d6677..4da61429fcce70f15198b405e1097cc1914a2445 100644 --- a/clang/lib/Sema/OpenCLBuiltins.td +++ b/clang/lib/Sema/OpenCLBuiltins.td @@ -1852,6 +1852,20 @@ let Extension = FunctionExtension<"cl_khr_subgroup_rotate"> in { def : Builtin<"sub_group_clustered_rotate", [AGenType1, AGenType1, Int, UInt], Attr.Convergent>; } +// cl_khr_kernel_clock +let Extension = FunctionExtension<"cl_khr_kernel_clock __opencl_c_kernel_clock_scope_device"> in { + def : Builtin<"clock_read_device", [ULong]>; + def : Builtin<"clock_read_hilo_device", [VectorType]>; +} +let Extension = FunctionExtension<"cl_khr_kernel_clock __opencl_c_kernel_clock_scope_work_group"> in { + def : Builtin<"clock_read_work_group", [ULong]>; + def : Builtin<"clock_read_hilo_work_group", [VectorType]>; +} +let Extension = FunctionExtension<"cl_khr_kernel_clock __opencl_c_kernel_clock_scope_sub_group"> in { + def : Builtin<"clock_read_sub_group", [ULong]>; + def : Builtin<"clock_read_hilo_sub_group", [VectorType]>; +} + //-------------------------------------------------------------------- // Arm extensions. let Extension = ArmIntegerDotProductInt8 in { diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 5d6ce233c775d84c8b54ca459fec43ef954f10f7..f847c49920cf3dca5e504edfc704798f15d27db9 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -42,6 +42,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaCUDA.h" +#include "clang/Sema/SemaCodeCompletion.h" #include "clang/Sema/SemaConsumer.h" #include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" @@ -202,6 +203,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), CurContext(nullptr), ExternalSource(nullptr), CurScope(nullptr), Ident_super(nullptr), + CodeCompletionPtr( + std::make_unique(*this, CodeCompleter)), CUDAPtr(std::make_unique(*this)), HLSLPtr(std::make_unique(*this)), ObjCPtr(std::make_unique(*this)), @@ -225,8 +228,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, TyposCorrected(0), IsBuildingRecoveryCallExpr(false), NumSFINAEErrors(0), AccessCheckingSFINAE(false), CurrentInstantiationScope(nullptr), InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0), - ArgumentPackSubstitutionIndex(-1), SatisfactionCache(Context), - CodeCompleter(CodeCompleter) { + ArgumentPackSubstitutionIndex(-1), SatisfactionCache(Context) { assert(pp.TUKind == TUKind); TUScope = nullptr; @@ -2054,9 +2056,15 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) { if (Ty->isSVESizelessBuiltinType() && FD && FD->hasBody()) { llvm::StringMap CallerFeatureMap; Context.getFunctionFeatureMap(CallerFeatureMap, FD); - if (!Builtin::evaluateRequiredTargetFeatures("sve", CallerFeatureMap) && - !Builtin::evaluateRequiredTargetFeatures("sme", CallerFeatureMap)) - Diag(D->getLocation(), diag::err_sve_vector_in_non_sve_target) << Ty; + if (!Builtin::evaluateRequiredTargetFeatures("sve", CallerFeatureMap)) { + if (!Builtin::evaluateRequiredTargetFeatures("sme", CallerFeatureMap)) + Diag(D->getLocation(), diag::err_sve_vector_in_non_sve_target) << Ty; + else if (!IsArmStreamingFunction(FD, + /*IncludeLocallyStreaming=*/true)) { + Diag(D->getLocation(), diag::err_sve_vector_in_non_streaming_function) + << Ty; + } + } } }; @@ -2456,7 +2464,7 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy, const OverloadExpr *Overloads = nullptr; bool IsMemExpr = false; if (E.getType() == Context.OverloadTy) { - OverloadExpr::FindResult FR = OverloadExpr::find(const_cast(&E)); + OverloadExpr::FindResult FR = OverloadExpr::find(&E); // Ignore overloads that are pointer-to-member constants. if (FR.HasFormOfMemberPointer) diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index 443bf162044ff7281417e771b14b9759941bb6fc..c80b08e361cfa60255b57a0d49cc34601f1ae48d 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -269,7 +269,8 @@ static void ProcessAPINotes(Sema &S, Decl *D, ASTAllocateString(S.Context, Info.UnavailableMsg), /*Strict=*/false, /*Replacement=*/StringRef(), - /*Priority=*/Sema::AP_Explicit); + /*Priority=*/Sema::AP_Explicit, + /*Environment=*/nullptr); }, [](const Decl *D) { return llvm::find_if(D->attrs(), [](const Attr *next) -> bool { diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp index 5ebc25317bf371deb74c2210acbc97b213cefa86..663b6f35b869d5a434a876272d03ebe457f45003 100644 --- a/clang/lib/Sema/SemaAvailability.cpp +++ b/clang/lib/Sema/SemaAvailability.cpp @@ -14,20 +14,37 @@ #include "clang/AST/Decl.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaObjC.h" +#include "llvm/ADT/StringRef.h" #include using namespace clang; using namespace sema; +static bool hasMatchingEnvironmentOrNone(const ASTContext &Context, + const AvailabilityAttr *AA) { + IdentifierInfo *IIEnvironment = AA->getEnvironment(); + auto Environment = Context.getTargetInfo().getTriple().getEnvironment(); + if (!IIEnvironment || Environment == llvm::Triple::UnknownEnvironment) + return true; + + llvm::Triple::EnvironmentType ET = + AvailabilityAttr::getEnvironmentType(IIEnvironment->getName()); + return Environment == ET; +} + static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context, const Decl *D) { + AvailabilityAttr const *PartialMatch = nullptr; // Check each AvailabilityAttr to find the one for this platform. + // For multiple attributes with the same platform try to find one for this + // environment. for (const auto *A : D->attrs()) { if (const auto *Avail = dyn_cast(A)) { // FIXME: this is copied from CheckAvailability. We should try to @@ -46,11 +63,15 @@ static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context, StringRef TargetPlatform = Context.getTargetInfo().getPlatformName(); // Match the platform name. - if (RealizedPlatform == TargetPlatform) - return Avail; + if (RealizedPlatform == TargetPlatform) { + // Find the best matching attribute for this environment + if (hasMatchingEnvironmentOrNone(Context, Avail)) + return Avail; + PartialMatch = Avail; + } } } - return nullptr; + return PartialMatch; } /// The diagnostic we should emit for \c D, and the declaration that @@ -118,10 +139,9 @@ ShouldDiagnoseAvailabilityOfDecl(Sema &S, const NamedDecl *D, /// whether we should emit a diagnostic for \c K and \c DeclVersion in /// the context of \c Ctx. For example, we should emit an unavailable diagnostic /// in a deprecated context, but not the other way around. -static bool -ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K, - VersionTuple DeclVersion, Decl *Ctx, - const NamedDecl *OffendingDecl) { +static bool ShouldDiagnoseAvailabilityInContext( + Sema &S, AvailabilityResult K, VersionTuple DeclVersion, + const IdentifierInfo *DeclEnv, Decl *Ctx, const NamedDecl *OffendingDecl) { assert(K != AR_Available && "Expected an unavailable declaration here!"); // If this was defined using CF_OPTIONS, etc. then ignore the diagnostic. @@ -140,7 +160,8 @@ ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K, auto CheckContext = [&](const Decl *C) { if (K == AR_NotYetIntroduced) { if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, C)) - if (AA->getIntroduced() >= DeclVersion) + if (AA->getIntroduced() >= DeclVersion && + AA->getEnvironment() == DeclEnv) return true; } else if (K == AR_Deprecated) { if (C->isDeprecated()) @@ -344,10 +365,14 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, unsigned available_here_select_kind; VersionTuple DeclVersion; - if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, OffendingDecl)) + const AvailabilityAttr *AA = getAttrForPlatform(S.Context, OffendingDecl); + const IdentifierInfo *IIEnv = nullptr; + if (AA) { DeclVersion = AA->getIntroduced(); + IIEnv = AA->getEnvironment(); + } - if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx, + if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, IIEnv, Ctx, OffendingDecl)) return; @@ -355,8 +380,7 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, // The declaration can have multiple availability attributes, we are looking // at one of them. - const AvailabilityAttr *A = getAttrForPlatform(S.Context, OffendingDecl); - if (A && A->isInherited()) { + if (AA && AA->isInherited()) { for (const Decl *Redecl = OffendingDecl->getMostRecentDecl(); Redecl; Redecl = Redecl->getPreviousDecl()) { const AvailabilityAttr *AForRedecl = @@ -376,26 +400,43 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, // not specified for deployment targets >= to iOS 11 or equivalent or // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or // later. - const AvailabilityAttr *AA = - getAttrForPlatform(S.getASTContext(), OffendingDecl); + assert(AA != nullptr && "expecting valid availability attribute"); VersionTuple Introduced = AA->getIntroduced(); + bool EnvironmentMatchesOrNone = + hasMatchingEnvironmentOrNone(S.getASTContext(), AA); + + const TargetInfo &TI = S.getASTContext().getTargetInfo(); + std::string PlatformName( + AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName())); + llvm::StringRef TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName( + TI.getTriple().getEnvironmentName())); + llvm::StringRef AttrEnvironment = + AA->getEnvironment() ? AvailabilityAttr::getPrettyEnviromentName( + AA->getEnvironment()->getName()) + : ""; + bool UseEnvironment = + (!AttrEnvironment.empty() && !TargetEnvironment.empty()); bool UseNewWarning = shouldDiagnoseAvailabilityByDefault( S.Context, S.Context.getTargetInfo().getPlatformMinVersion(), Introduced); - unsigned Warning = UseNewWarning ? diag::warn_unguarded_availability_new - : diag::warn_unguarded_availability; - std::string PlatformName(AvailabilityAttr::getPrettyPlatformName( - S.getASTContext().getTargetInfo().getPlatformName())); + unsigned DiagKind = + EnvironmentMatchesOrNone + ? (UseNewWarning ? diag::warn_unguarded_availability_new + : diag::warn_unguarded_availability) + : (UseNewWarning ? diag::warn_unguarded_availability_unavailable_new + : diag::warn_unguarded_availability_unavailable); - S.Diag(Loc, Warning) << OffendingDecl << PlatformName - << Introduced.getAsString(); + S.Diag(Loc, DiagKind) << OffendingDecl << PlatformName + << Introduced.getAsString() << UseEnvironment + << TargetEnvironment; S.Diag(OffendingDecl->getLocation(), diag::note_partial_availability_specified_here) << OffendingDecl << PlatformName << Introduced.getAsString() - << S.Context.getTargetInfo().getPlatformMinVersion().getAsString(); + << S.Context.getTargetInfo().getPlatformMinVersion().getAsString() + << UseEnvironment << AttrEnvironment << TargetEnvironment; if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) { if (const auto *TD = dyn_cast(Enclosing)) @@ -772,14 +813,17 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( const AvailabilityAttr *AA = getAttrForPlatform(SemaRef.getASTContext(), OffendingDecl); + bool EnvironmentMatchesOrNone = + hasMatchingEnvironmentOrNone(SemaRef.getASTContext(), AA); VersionTuple Introduced = AA->getIntroduced(); - if (AvailabilityStack.back() >= Introduced) + if (EnvironmentMatchesOrNone && AvailabilityStack.back() >= Introduced) return; // If the context of this function is less available than D, we should not // emit a diagnostic. - if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced, Ctx, + if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced, + AA->getEnvironment(), Ctx, OffendingDecl)) return; @@ -787,25 +831,39 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( // not specified for deployment targets >= to iOS 11 or equivalent or // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or // later. - unsigned DiagKind = - shouldDiagnoseAvailabilityByDefault( - SemaRef.Context, - SemaRef.Context.getTargetInfo().getPlatformMinVersion(), Introduced) - ? diag::warn_unguarded_availability_new - : diag::warn_unguarded_availability; + bool UseNewDiagKind = shouldDiagnoseAvailabilityByDefault( + SemaRef.Context, + SemaRef.Context.getTargetInfo().getPlatformMinVersion(), Introduced); + + const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo(); + std::string PlatformName( + AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName())); + llvm::StringRef TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName( + TI.getTriple().getEnvironmentName())); + llvm::StringRef AttrEnvironment = + AA->getEnvironment() ? AvailabilityAttr::getPrettyEnviromentName( + AA->getEnvironment()->getName()) + : ""; + bool UseEnvironment = + (!AttrEnvironment.empty() && !TargetEnvironment.empty()); - std::string PlatformName(AvailabilityAttr::getPrettyPlatformName( - SemaRef.getASTContext().getTargetInfo().getPlatformName())); + unsigned DiagKind = + EnvironmentMatchesOrNone + ? (UseNewDiagKind ? diag::warn_unguarded_availability_new + : diag::warn_unguarded_availability) + : (UseNewDiagKind + ? diag::warn_unguarded_availability_unavailable_new + : diag::warn_unguarded_availability_unavailable); SemaRef.Diag(Range.getBegin(), DiagKind) - << Range << D << PlatformName << Introduced.getAsString(); + << Range << D << PlatformName << Introduced.getAsString() + << UseEnvironment << TargetEnvironment; SemaRef.Diag(OffendingDecl->getLocation(), diag::note_partial_availability_specified_here) << OffendingDecl << PlatformName << Introduced.getAsString() - << SemaRef.Context.getTargetInfo() - .getPlatformMinVersion() - .getAsString(); + << SemaRef.Context.getTargetInfo().getPlatformMinVersion().getAsString() + << UseEnvironment << AttrEnvironment << TargetEnvironment; auto FixitDiag = SemaRef.Diag(Range.getBegin(), diag::note_unguarded_available_silence) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index ecd1821651140b4abf97b908a53daa06bd13f264..f2dc8e9dd005068601511d95d9129df6ca3e19d8 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -8092,6 +8092,12 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, diagnoseArgDependentDiagnoseIfAttrs(FD, ThisArg, Args, Loc); } +void Sema::CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc) { + if (ConceptDecl *Decl = AutoT->getTypeConstraintConcept()) { + DiagnoseUseOfDecl(Decl, Loc); + } +} + /// CheckConstructorCall - Check a constructor call for correctness and safety /// properties not enforced by the C type system. void Sema::CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType, diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 328641ed94881f75a5d201624af07fcab1ec01a4..ad3ca4cc94ca638a34c03b2bfa2b42049d736ac3 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -41,6 +41,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaCodeCompletion.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" #include "llvm/ADT/ArrayRef.h" @@ -246,8 +247,8 @@ public: /// Whether we should include code patterns in the completion /// results. bool includeCodePatterns() const { - return SemaRef.CodeCompleter && - SemaRef.CodeCompleter->includeCodePatterns(); + return SemaRef.CodeCompletion().CodeCompleter && + SemaRef.CodeCompletion().CodeCompleter->includeCodePatterns(); } /// Set the filter used for code-completion results. @@ -1863,9 +1864,9 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, Results.AddResult(Result("_Nullable", CCP_Type)); } -static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC, - const LangOptions &LangOpts, - ResultBuilder &Results) { +static void +AddStorageSpecifiers(SemaCodeCompletion::ParserCompletionContext CCC, + const LangOptions &LangOpts, ResultBuilder &Results) { typedef CodeCompletionResult Result; // Note: we don't suggest either "auto" or "register", because both // are pointless as storage specifiers. Elsewhere, we suggest "auto" @@ -1889,13 +1890,13 @@ static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC, } } -static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC, - const LangOptions &LangOpts, - ResultBuilder &Results) { +static void +AddFunctionSpecifiers(SemaCodeCompletion::ParserCompletionContext CCC, + const LangOptions &LangOpts, ResultBuilder &Results) { typedef CodeCompletionResult Result; switch (CCC) { - case Sema::PCC_Class: - case Sema::PCC_MemberTemplate: + case SemaCodeCompletion::PCC_Class: + case SemaCodeCompletion::PCC_MemberTemplate: if (LangOpts.CPlusPlus) { Results.AddResult(Result("explicit")); Results.AddResult(Result("friend")); @@ -1904,24 +1905,24 @@ static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC, } [[fallthrough]]; - case Sema::PCC_ObjCInterface: - case Sema::PCC_ObjCImplementation: - case Sema::PCC_Namespace: - case Sema::PCC_Template: + case SemaCodeCompletion::PCC_ObjCInterface: + case SemaCodeCompletion::PCC_ObjCImplementation: + case SemaCodeCompletion::PCC_Namespace: + case SemaCodeCompletion::PCC_Template: if (LangOpts.CPlusPlus || LangOpts.C99) Results.AddResult(Result("inline")); break; - case Sema::PCC_ObjCInstanceVariableList: - case Sema::PCC_Expression: - case Sema::PCC_Statement: - case Sema::PCC_TopLevelOrExpression: - case Sema::PCC_ForInit: - case Sema::PCC_Condition: - case Sema::PCC_RecoveryInFunction: - case Sema::PCC_Type: - case Sema::PCC_ParenthesizedExpression: - case Sema::PCC_LocalDeclarationSpecifiers: + case SemaCodeCompletion::PCC_ObjCInstanceVariableList: + case SemaCodeCompletion::PCC_Expression: + case SemaCodeCompletion::PCC_Statement: + case SemaCodeCompletion::PCC_TopLevelOrExpression: + case SemaCodeCompletion::PCC_ForInit: + case SemaCodeCompletion::PCC_Condition: + case SemaCodeCompletion::PCC_RecoveryInFunction: + case SemaCodeCompletion::PCC_Type: + case SemaCodeCompletion::PCC_ParenthesizedExpression: + case SemaCodeCompletion::PCC_LocalDeclarationSpecifiers: break; } } @@ -1960,31 +1961,31 @@ static void AddUsingAliasResult(CodeCompletionBuilder &Builder, Results.AddResult(CodeCompletionResult(Builder.TakeString())); } -static bool WantTypesInContext(Sema::ParserCompletionContext CCC, +static bool WantTypesInContext(SemaCodeCompletion::ParserCompletionContext CCC, const LangOptions &LangOpts) { switch (CCC) { - case Sema::PCC_Namespace: - case Sema::PCC_Class: - case Sema::PCC_ObjCInstanceVariableList: - case Sema::PCC_Template: - case Sema::PCC_MemberTemplate: - case Sema::PCC_Statement: - case Sema::PCC_RecoveryInFunction: - case Sema::PCC_Type: - case Sema::PCC_ParenthesizedExpression: - case Sema::PCC_LocalDeclarationSpecifiers: - case Sema::PCC_TopLevelOrExpression: + case SemaCodeCompletion::PCC_Namespace: + case SemaCodeCompletion::PCC_Class: + case SemaCodeCompletion::PCC_ObjCInstanceVariableList: + case SemaCodeCompletion::PCC_Template: + case SemaCodeCompletion::PCC_MemberTemplate: + case SemaCodeCompletion::PCC_Statement: + case SemaCodeCompletion::PCC_RecoveryInFunction: + case SemaCodeCompletion::PCC_Type: + case SemaCodeCompletion::PCC_ParenthesizedExpression: + case SemaCodeCompletion::PCC_LocalDeclarationSpecifiers: + case SemaCodeCompletion::PCC_TopLevelOrExpression: return true; - case Sema::PCC_Expression: - case Sema::PCC_Condition: + case SemaCodeCompletion::PCC_Expression: + case SemaCodeCompletion::PCC_Condition: return LangOpts.CPlusPlus; - case Sema::PCC_ObjCInterface: - case Sema::PCC_ObjCImplementation: + case SemaCodeCompletion::PCC_ObjCInterface: + case SemaCodeCompletion::PCC_ObjCImplementation: return false; - case Sema::PCC_ForInit: + case SemaCodeCompletion::PCC_ForInit: return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99; } @@ -2131,14 +2132,15 @@ static void AddOverrideResults(ResultBuilder &Results, } /// Add language constructs that show up for "ordinary" names. -static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, - Sema &SemaRef, ResultBuilder &Results) { +static void +AddOrdinaryNameResults(SemaCodeCompletion::ParserCompletionContext CCC, + Scope *S, Sema &SemaRef, ResultBuilder &Results) { CodeCompletionAllocator &Allocator = Results.getAllocator(); CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); typedef CodeCompletionResult Result; switch (CCC) { - case Sema::PCC_Namespace: + case SemaCodeCompletion::PCC_Namespace: if (SemaRef.getLangOpts().CPlusPlus) { if (Results.includeCodePatterns()) { // namespace { declarations } @@ -2194,7 +2196,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, AddTypedefResult(Results); [[fallthrough]]; - case Sema::PCC_Class: + case SemaCodeCompletion::PCC_Class: if (SemaRef.getLangOpts().CPlusPlus) { // Using declaration Builder.AddTypedTextChunk("using"); @@ -2221,7 +2223,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts()); - if (CCC == Sema::PCC_Class) { + if (CCC == SemaCodeCompletion::PCC_Class) { AddTypedefResult(Results); bool IsNotInheritanceScope = !S->isClassInheritanceScope(); @@ -2252,8 +2254,8 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, } [[fallthrough]]; - case Sema::PCC_Template: - case Sema::PCC_MemberTemplate: + case SemaCodeCompletion::PCC_Template: + case SemaCodeCompletion::PCC_MemberTemplate: if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) { // template < parameters > Builder.AddTypedTextChunk("template"); @@ -2269,25 +2271,25 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); break; - case Sema::PCC_ObjCInterface: + case SemaCodeCompletion::PCC_ObjCInterface: AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true); AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); break; - case Sema::PCC_ObjCImplementation: + case SemaCodeCompletion::PCC_ObjCImplementation: AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true); AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); break; - case Sema::PCC_ObjCInstanceVariableList: + case SemaCodeCompletion::PCC_ObjCInstanceVariableList: AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true); break; - case Sema::PCC_RecoveryInFunction: - case Sema::PCC_TopLevelOrExpression: - case Sema::PCC_Statement: { + case SemaCodeCompletion::PCC_RecoveryInFunction: + case SemaCodeCompletion::PCC_TopLevelOrExpression: + case SemaCodeCompletion::PCC_Statement: { if (SemaRef.getLangOpts().CPlusPlus11) AddUsingAliasResult(Builder, Results); @@ -2524,15 +2526,15 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, [[fallthrough]]; // Fall through (for statement expressions). - case Sema::PCC_ForInit: - case Sema::PCC_Condition: + case SemaCodeCompletion::PCC_ForInit: + case SemaCodeCompletion::PCC_Condition: AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); // Fall through: conditions and statements can have expressions. [[fallthrough]]; - case Sema::PCC_ParenthesizedExpression: + case SemaCodeCompletion::PCC_ParenthesizedExpression: if (SemaRef.getLangOpts().ObjCAutoRefCount && - CCC == Sema::PCC_ParenthesizedExpression) { + CCC == SemaCodeCompletion::PCC_ParenthesizedExpression) { // (__bridge ) Builder.AddTypedTextChunk("__bridge"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -2560,7 +2562,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, // Fall through [[fallthrough]]; - case Sema::PCC_Expression: { + case SemaCodeCompletion::PCC_Expression: { if (SemaRef.getLangOpts().CPlusPlus) { // 'this', if we're in a non-static member function. addThisCompletion(SemaRef, Results); @@ -2758,15 +2760,15 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, break; } - case Sema::PCC_Type: - case Sema::PCC_LocalDeclarationSpecifiers: + case SemaCodeCompletion::PCC_Type: + case SemaCodeCompletion::PCC_LocalDeclarationSpecifiers: break; } if (WantTypesInContext(CCC, SemaRef.getLangOpts())) AddTypeSpecifierResults(SemaRef.getLangOpts(), Results); - if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type) + if (SemaRef.getLangOpts().CPlusPlus && CCC != SemaCodeCompletion::PCC_Type) Results.AddResult(Result("operator")); } @@ -4241,59 +4243,60 @@ static void HandleCodeCompleteResults(Sema *S, } static CodeCompletionContext -mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) { +mapCodeCompletionContext(Sema &S, + SemaCodeCompletion::ParserCompletionContext PCC) { switch (PCC) { - case Sema::PCC_Namespace: + case SemaCodeCompletion::PCC_Namespace: return CodeCompletionContext::CCC_TopLevel; - case Sema::PCC_Class: + case SemaCodeCompletion::PCC_Class: return CodeCompletionContext::CCC_ClassStructUnion; - case Sema::PCC_ObjCInterface: + case SemaCodeCompletion::PCC_ObjCInterface: return CodeCompletionContext::CCC_ObjCInterface; - case Sema::PCC_ObjCImplementation: + case SemaCodeCompletion::PCC_ObjCImplementation: return CodeCompletionContext::CCC_ObjCImplementation; - case Sema::PCC_ObjCInstanceVariableList: + case SemaCodeCompletion::PCC_ObjCInstanceVariableList: return CodeCompletionContext::CCC_ObjCIvarList; - case Sema::PCC_Template: - case Sema::PCC_MemberTemplate: + case SemaCodeCompletion::PCC_Template: + case SemaCodeCompletion::PCC_MemberTemplate: if (S.CurContext->isFileContext()) return CodeCompletionContext::CCC_TopLevel; if (S.CurContext->isRecord()) return CodeCompletionContext::CCC_ClassStructUnion; return CodeCompletionContext::CCC_Other; - case Sema::PCC_RecoveryInFunction: + case SemaCodeCompletion::PCC_RecoveryInFunction: return CodeCompletionContext::CCC_Recovery; - case Sema::PCC_ForInit: + case SemaCodeCompletion::PCC_ForInit: if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 || S.getLangOpts().ObjC) return CodeCompletionContext::CCC_ParenthesizedExpression; else return CodeCompletionContext::CCC_Expression; - case Sema::PCC_Expression: + case SemaCodeCompletion::PCC_Expression: return CodeCompletionContext::CCC_Expression; - case Sema::PCC_Condition: + case SemaCodeCompletion::PCC_Condition: return CodeCompletionContext(CodeCompletionContext::CCC_Expression, S.getASTContext().BoolTy); - case Sema::PCC_Statement: + case SemaCodeCompletion::PCC_Statement: return CodeCompletionContext::CCC_Statement; - case Sema::PCC_Type: + case SemaCodeCompletion::PCC_Type: return CodeCompletionContext::CCC_Type; - case Sema::PCC_ParenthesizedExpression: + case SemaCodeCompletion::PCC_ParenthesizedExpression: return CodeCompletionContext::CCC_ParenthesizedExpression; - case Sema::PCC_LocalDeclarationSpecifiers: + case SemaCodeCompletion::PCC_LocalDeclarationSpecifiers: return CodeCompletionContext::CCC_Type; - case Sema::PCC_TopLevelOrExpression: + case SemaCodeCompletion::PCC_TopLevelOrExpression: return CodeCompletionContext::CCC_TopLevelOrExpression; } @@ -4366,10 +4369,10 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, } } -void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, - ModuleIdPath Path) { +void SemaCodeCompletion::CodeCompleteModuleImport(SourceLocation ImportLoc, + ModuleIdPath Path) { typedef CodeCompletionResult Result; - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); @@ -4380,7 +4383,7 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, if (Path.empty()) { // Enumerate all top-level modules. SmallVector Modules; - PP.getHeaderSearchInfo().collectAllModules(Modules); + SemaRef.PP.getHeaderSearchInfo().collectAllModules(Modules); for (unsigned I = 0, N = Modules.size(); I != N; ++I) { Builder.AddTypedTextChunk( Builder.getAllocator().CopyString(Modules[I]->Name)); @@ -4391,9 +4394,9 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, } } else if (getLangOpts().Modules) { // Load the named module. - Module *Mod = - PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible, - /*IsInclusionDirective=*/false); + Module *Mod = SemaRef.PP.getModuleLoader().loadModule( + ImportLoc, Path, Module::AllVisible, + /*IsInclusionDirective=*/false); // Enumerate submodules. if (Mod) { for (auto *Submodule : Mod->submodules()) { @@ -4407,15 +4410,16 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, } } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteOrdinaryName(Scope *S, - ParserCompletionContext CompletionContext) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteOrdinaryName( + Scope *S, SemaCodeCompletion::ParserCompletionContext CompletionContext) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), - mapCodeCompletionContext(*this, CompletionContext)); + mapCodeCompletionContext(SemaRef, CompletionContext)); Results.EnterNewScope(); // Determine how to filter results, e.g., so that the names of @@ -4446,7 +4450,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); if (getLangOpts().CPlusPlus) - MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results); + MaybeAddOverrideCalls(SemaRef, /*InContext=*/nullptr, Results); break; case PCC_RecoveryInFunction: @@ -4456,17 +4460,17 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, // If we are in a C++ non-static member function, check the qualifiers on // the member function to filter/prioritize the results list. - auto ThisType = getCurrentThisType(); + auto ThisType = SemaRef.getCurrentThisType(); if (!ThisType.isNull()) Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers(), VK_LValue); - CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals(), - CodeCompleter->loadExternal()); + CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext); + SemaRef.LookupVisibleDecls(S, SemaRef.LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); - AddOrdinaryNameResults(CompletionContext, S, *this, Results); + AddOrdinaryNameResults(CompletionContext, S, SemaRef, Results); Results.ExitScope(); switch (CompletionContext) { @@ -4494,10 +4498,11 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, } if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); + AddMacroResults(SemaRef.PP, Results, CodeCompleter->loadExternal(), false); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } static void @@ -4506,12 +4511,12 @@ AddClassMessageCompletions(Sema &SemaRef, Scope *S, ParsedType Receiver, bool AtArgumentExpression, bool IsSuper, ResultBuilder &Results); -void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, - bool AllowNonIdentifiers, - bool AllowNestedNameSpecifiers) { +void SemaCodeCompletion::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, + bool AllowNonIdentifiers, + bool AllowNestedNameSpecifiers) { typedef CodeCompletionResult Result; ResultBuilder Results( - *this, CodeCompleter->getAllocator(), + SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), AllowNestedNameSpecifiers // FIXME: Try to separate codepath leading here to deduce whether we @@ -4540,10 +4545,10 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, if (AllowNestedNameSpecifiers) { Results.allowNestedNameSpecifiers(); Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy); - CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer, - CodeCompleter->includeGlobals(), - CodeCompleter->loadExternal()); + CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext); + SemaRef.LookupVisibleDecls(S, Sema::LookupNestedNameSpecifierName, + Consumer, CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); Results.setFilter(nullptr); } } @@ -4565,15 +4570,16 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, 0) { ParsedType T = DS.getRepAsType(); if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType()) - AddClassMessageCompletions(*this, S, T, std::nullopt, false, false, + AddClassMessageCompletions(SemaRef, S, T, std::nullopt, false, false, Results); } // Note that we intentionally suppress macro results here, since we do not // encourage using macros to produce the names of entities. - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } static const char *underscoreAttrScope(llvm::StringRef Scope) { @@ -4592,12 +4598,12 @@ static const char *noUnderscoreAttrScope(llvm::StringRef Scope) { return nullptr; } -void Sema::CodeCompleteAttribute(AttributeCommonInfo::Syntax Syntax, - AttributeCompletion Completion, - const IdentifierInfo *InScope) { +void SemaCodeCompletion::CodeCompleteAttribute( + AttributeCommonInfo::Syntax Syntax, AttributeCompletion Completion, + const IdentifierInfo *InScope) { if (Completion == AttributeCompletion::None) return; - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Attribute); @@ -4626,7 +4632,8 @@ void Sema::CodeCompleteAttribute(AttributeCommonInfo::Syntax Syntax, llvm::DenseSet FoundScopes; auto AddCompletions = [&](const ParsedAttrInfo &A) { - if (A.IsTargetSpecific && !A.existsInTarget(Context.getTargetInfo())) + if (A.IsTargetSpecific && + !A.existsInTarget(getASTContext().getTargetInfo())) return; if (!A.acceptsLangOpts(getLangOpts())) return; @@ -4724,11 +4731,12 @@ void Sema::CodeCompleteAttribute(AttributeCommonInfo::Syntax Syntax, for (const auto &Entry : ParsedAttrInfoRegistry::entries()) AddCompletions(*Entry.instantiate()); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -struct Sema::CodeCompleteExpressionData { +struct SemaCodeCompletion::CodeCompleteExpressionData { CodeCompleteExpressionData(QualType PreferredType = QualType(), bool IsParenthesized = false) : PreferredType(PreferredType), IntegralConstantExpression(false), @@ -4841,10 +4849,10 @@ static void AddLambdaCompletion(ResultBuilder &Results, /// Perform code-completion in an expression context when we know what /// type we're looking for. -void Sema::CodeCompleteExpression(Scope *S, - const CodeCompleteExpressionData &Data) { +void SemaCodeCompletion::CodeCompleteExpression( + Scope *S, const CodeCompleteExpressionData &Data) { ResultBuilder Results( - *this, CodeCompleter->getAllocator(), + SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext( Data.IsParenthesized @@ -4869,13 +4877,13 @@ void Sema::CodeCompleteExpression(Scope *S, for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I) Results.Ignore(Data.IgnoreDecls[I]); - CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals(), - CodeCompleter->loadExternal()); + CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext); + SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); Results.EnterNewScope(); - AddOrdinaryNameResults(PCC, S, *this, Results); + AddOrdinaryNameResults(PCC, S, SemaRef, Results); Results.ExitScope(); bool PreferredTypeIsPointer = false; @@ -4889,7 +4897,8 @@ void Sema::CodeCompleteExpression(Scope *S, Enum = Def; // FIXME: collect covered enumerators in cases like: // if (x == my_enum::one) { ... } else if (x == ^) {} - AddEnumerators(Results, Context, Enum, CurContext, CoveredEnumerators()); + AddEnumerators(Results, getASTContext(), Enum, SemaRef.CurContext, + CoveredEnumerators()); } } @@ -4898,7 +4907,7 @@ void Sema::CodeCompleteExpression(Scope *S, AddPrettyFunctionResults(getLangOpts(), Results); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false, + AddMacroResults(SemaRef.PP, Results, CodeCompleter->loadExternal(), false, PreferredTypeIsPointer); // Complete a lambda expression when preferred type is a function. @@ -4908,18 +4917,20 @@ void Sema::CodeCompleteExpression(Scope *S, AddLambdaCompletion(Results, F->getParamTypes(), getLangOpts()); } - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType, - bool IsParenthesized) { +void SemaCodeCompletion::CodeCompleteExpression(Scope *S, + QualType PreferredType, + bool IsParenthesized) { return CodeCompleteExpression( S, CodeCompleteExpressionData(PreferredType, IsParenthesized)); } -void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E, - QualType PreferredType) { +void SemaCodeCompletion::CodeCompletePostfixExpression(Scope *S, ExprResult E, + QualType PreferredType) { if (E.isInvalid()) CodeCompleteExpression(S, PreferredType); else if (getLangOpts().ObjC) @@ -5182,10 +5193,11 @@ AddRecordMembersCompletionResults(Sema &SemaRef, ResultBuilder &Results, if (AccessOpFixIt) FixIts.emplace_back(*AccessOpFixIt); CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts)); - SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer, - SemaRef.CodeCompleter->includeGlobals(), - /*IncludeDependentBases=*/true, - SemaRef.CodeCompleter->loadExternal()); + SemaRef.LookupVisibleDecls( + RD, Sema::LookupMemberName, Consumer, + SemaRef.CodeCompletion().CodeCompleter->includeGlobals(), + /*IncludeDependentBases=*/true, + SemaRef.CodeCompletion().CodeCompleter->loadExternal()); if (SemaRef.getLangOpts().CPlusPlus) { if (!Results.empty()) { @@ -5701,17 +5713,16 @@ Expr *unwrapParenList(Expr *Base) { } // namespace -void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, - Expr *OtherOpBase, - SourceLocation OpLoc, bool IsArrow, - bool IsBaseExprStatement, - QualType PreferredType) { +void SemaCodeCompletion::CodeCompleteMemberReferenceExpr( + Scope *S, Expr *Base, Expr *OtherOpBase, SourceLocation OpLoc, bool IsArrow, + bool IsBaseExprStatement, QualType PreferredType) { Base = unwrapParenList(Base); OtherOpBase = unwrapParenList(OtherOpBase); if (!Base || !CodeCompleter) return; - ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow); + ExprResult ConvertedBase = + SemaRef.PerformMemberExprBaseConversion(Base, IsArrow); if (ConvertedBase.isInvalid()) return; QualType ConvertedBaseType = getApproximateType(ConvertedBase.get()); @@ -5736,7 +5747,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, CodeCompletionContext CCContext(contextKind, ConvertedBaseType); CCContext.setPreferredType(PreferredType); - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CCContext, &ResultBuilder::IsMember); @@ -5745,7 +5756,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, if (!Base) return false; - ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow); + ExprResult ConvertedBase = + SemaRef.PerformMemberExprBaseConversion(Base, IsArrow); if (ConvertedBase.isInvalid()) return false; Base = ConvertedBase.get(); @@ -5768,7 +5780,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, } if (RecordDecl *RD = getAsRecordDecl(BaseType)) { - AddRecordMembersCompletionResults(*this, Results, S, BaseType, BaseKind, + AddRecordMembersCompletionResults(SemaRef, Results, S, BaseType, BaseKind, RD, std::move(AccessOpFixIt)); } else if (const auto *TTPT = dyn_cast(BaseType.getTypePtr())) { @@ -5778,7 +5790,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, if (R.Operator != Operator) continue; CodeCompletionResult Result( - R.render(*this, CodeCompleter->getAllocator(), + R.render(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo())); if (AccessOpFixIt) Result.FixIts.push_back(*AccessOpFixIt); @@ -5798,14 +5810,14 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, // Add property results based on our interface. assert(ObjCPtr && "Non-NULL pointer guaranteed above!"); AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true, - /*AllowNullaryMethods=*/true, CurContext, + /*AllowNullaryMethods=*/true, SemaRef.CurContext, AddedProperties, Results, IsBaseExprStatement); } // Add properties from the protocols in a qualified interface. for (auto *I : BaseType->castAs()->quals()) AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true, - CurContext, AddedProperties, Results, + SemaRef.CurContext, AddedProperties, Results, IsBaseExprStatement, /*IsClassProperty*/ false, /*InOriginalClass*/ false); } else if ((IsArrow && BaseType->isObjCObjectPointerType()) || @@ -5827,9 +5839,10 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, if (Class) { CodeCompletionDeclConsumer Consumer(Results, Class, BaseType); Results.setFilter(&ResultBuilder::IsObjCIvar); - LookupVisibleDecls( - Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(), - /*IncludeDependentBases=*/false, CodeCompleter->loadExternal()); + SemaRef.LookupVisibleDecls(Class, Sema::LookupMemberName, Consumer, + CodeCompleter->includeGlobals(), + /*IncludeDependentBases=*/false, + CodeCompleter->loadExternal()); } } @@ -5854,36 +5867,37 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, return; // Hand off the results found for code completion. - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S, - const IdentifierInfo &ClassName, - SourceLocation ClassNameLoc, - bool IsBaseExprStatement) { +void SemaCodeCompletion::CodeCompleteObjCClassPropertyRefExpr( + Scope *S, const IdentifierInfo &ClassName, SourceLocation ClassNameLoc, + bool IsBaseExprStatement) { const IdentifierInfo *ClassNamePtr = &ClassName; ObjCInterfaceDecl *IFace = - ObjC().getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc); + SemaRef.ObjC().getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc); if (!IFace) return; CodeCompletionContext CCContext( CodeCompletionContext::CCC_ObjCPropertyAccess); - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CCContext, &ResultBuilder::IsMember); Results.EnterNewScope(); AddedPropertiesSet AddedProperties; AddObjCProperties(CCContext, IFace, true, - /*AllowNullaryMethods=*/true, CurContext, AddedProperties, - Results, IsBaseExprStatement, + /*AllowNullaryMethods=*/true, SemaRef.CurContext, + AddedProperties, Results, IsBaseExprStatement, /*IsClassProperty=*/true); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { +void SemaCodeCompletion::CodeCompleteTag(Scope *S, unsigned TagSpec) { if (!CodeCompleter) return; @@ -5912,26 +5926,27 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { llvm_unreachable("Unknown type specifier kind in CodeCompleteTag"); } - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), ContextKind); - CodeCompletionDeclConsumer Consumer(Results, CurContext); + CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext); // First pass: look for tags. Results.setFilter(Filter); - LookupVisibleDecls(S, LookupTagName, Consumer, - CodeCompleter->includeGlobals(), - CodeCompleter->loadExternal()); + SemaRef.LookupVisibleDecls(S, Sema::LookupTagName, Consumer, + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); if (CodeCompleter->includeGlobals()) { // Second pass: look for nested name specifiers. Results.setFilter(&ResultBuilder::IsNestedNameSpecifier); - LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer, - CodeCompleter->includeGlobals(), - CodeCompleter->loadExternal()); + SemaRef.LookupVisibleDecls(S, Sema::LookupNestedNameSpecifierName, Consumer, + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); } - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results, @@ -5948,25 +5963,26 @@ static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results, Results.AddResult("__unaligned"); } -void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteTypeQualifiers(DeclSpec &DS) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_TypeQualifiers); Results.EnterNewScope(); - AddTypeQualifierResults(DS, Results, LangOpts); + AddTypeQualifierResults(DS, Results, getLangOpts()); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D, - const VirtSpecifiers *VS) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteFunctionQualifiers( + DeclSpec &DS, Declarator &D, const VirtSpecifiers *VS) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_TypeQualifiers); Results.EnterNewScope(); - AddTypeQualifierResults(DS, Results, LangOpts); - if (LangOpts.CPlusPlus11) { + AddTypeQualifierResults(DS, Results, getLangOpts()); + if (getLangOpts().CPlusPlus11) { Results.AddResult("noexcept"); if (D.getContext() == DeclaratorContext::Member && !D.isCtorOrDtor() && !D.isStaticMember()) { @@ -5977,19 +5993,21 @@ void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D, } } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteBracketDeclarator(Scope *S) { +void SemaCodeCompletion::CodeCompleteBracketDeclarator(Scope *S) { CodeCompleteExpression(S, QualType(getASTContext().getSizeType())); } -void Sema::CodeCompleteCase(Scope *S) { - if (getCurFunction()->SwitchStack.empty() || !CodeCompleter) +void SemaCodeCompletion::CodeCompleteCase(Scope *S) { + if (SemaRef.getCurFunction()->SwitchStack.empty() || !CodeCompleter) return; - SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer(); + SwitchStmt *Switch = + SemaRef.getCurFunction()->SwitchStack.back().getPointer(); // Condition expression might be invalid, do not continue in this case. if (!Switch->getCond()) return; @@ -6046,16 +6064,18 @@ void Sema::CodeCompleteCase(Scope *S) { } // Add any enumerators that have not yet been mentioned. - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Expression); - AddEnumerators(Results, Context, Enum, CurContext, Enumerators); + AddEnumerators(Results, getASTContext(), Enum, SemaRef.CurContext, + Enumerators); if (CodeCompleter->includeMacros()) { - AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); + AddMacroResults(SemaRef.PP, Results, CodeCompleter->loadExternal(), false); } - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } static bool anyNullArguments(ArrayRef Args) { @@ -6136,7 +6156,7 @@ ProduceSignatureHelp(Sema &SemaRef, MutableArrayRef Candidates, if (Candidates.empty()) return QualType(); if (SemaRef.getPreprocessor().isCodeCompletionReached()) - SemaRef.CodeCompleter->ProcessOverloadCandidates( + SemaRef.CodeCompletion().CodeCompleter->ProcessOverloadCandidates( SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc, Braced); return getParamType(SemaRef, Candidates, CurrentArg); @@ -6190,8 +6210,9 @@ static FunctionProtoTypeLoc GetPrototypeLoc(Expr *Fn) { return {}; } -QualType Sema::ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args, - SourceLocation OpenParLoc) { +QualType +SemaCodeCompletion::ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args, + SourceLocation OpenParLoc) { Fn = unwrapParenList(Fn); if (!CodeCompleter || !Fn) return QualType(); @@ -6214,8 +6235,9 @@ QualType Sema::ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args, OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); if (auto ULE = dyn_cast(NakedFn)) { - AddOverloadedCallCandidates(ULE, ArgsWithoutDependentTypes, CandidateSet, - /*PartialOverloading=*/true); + SemaRef.AddOverloadedCallCandidates(ULE, ArgsWithoutDependentTypes, + CandidateSet, + /*PartialOverloading=*/true); } else if (auto UME = dyn_cast(NakedFn)) { TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr; if (UME->hasExplicitTemplateArgs()) { @@ -6231,9 +6253,10 @@ QualType Sema::ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args, UnresolvedSet<8> Decls; Decls.append(UME->decls_begin(), UME->decls_end()); const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase(); - AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs, - /*SuppressUserConversions=*/false, - /*PartialOverloading=*/true, FirstArgumentIsBase); + SemaRef.AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs, + /*SuppressUserConversions=*/false, + /*PartialOverloading=*/true, + FirstArgumentIsBase); } else { FunctionDecl *FD = nullptr; if (auto *MCE = dyn_cast(NakedFn)) @@ -6245,28 +6268,30 @@ QualType Sema::ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args, !FD->getType()->getAs()) Results.push_back(ResultCandidate(FD)); else - AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()), - ArgsWithoutDependentTypes, CandidateSet, - /*SuppressUserConversions=*/false, - /*PartialOverloading=*/true); + SemaRef.AddOverloadCandidate(FD, + DeclAccessPair::make(FD, FD->getAccess()), + ArgsWithoutDependentTypes, CandidateSet, + /*SuppressUserConversions=*/false, + /*PartialOverloading=*/true); } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) { // If expression's type is CXXRecordDecl, it may overload the function // call operator, so we check if it does and add them as candidates. // A complete type is needed to lookup for member function call operators. - if (isCompleteType(Loc, NakedFn->getType())) { + if (SemaRef.isCompleteType(Loc, NakedFn->getType())) { DeclarationName OpName = - Context.DeclarationNames.getCXXOperatorName(OO_Call); - LookupResult R(*this, OpName, Loc, LookupOrdinaryName); - LookupQualifiedName(R, DC); + getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); + LookupResult R(SemaRef, OpName, Loc, Sema::LookupOrdinaryName); + SemaRef.LookupQualifiedName(R, DC); R.suppressDiagnostics(); SmallVector ArgExprs(1, NakedFn); ArgExprs.append(ArgsWithoutDependentTypes.begin(), ArgsWithoutDependentTypes.end()); - AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet, - /*ExplicitArgs=*/nullptr, - /*SuppressUserConversions=*/false, - /*PartialOverloading=*/true); + SemaRef.AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, + CandidateSet, + /*ExplicitArgs=*/nullptr, + /*SuppressUserConversions=*/false, + /*PartialOverloading=*/true); } } else { // Lastly we check whether expression's type is function pointer or @@ -6278,9 +6303,9 @@ QualType Sema::ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args, T = T->getPointeeType(); if (auto FP = T->getAs()) { - if (!TooManyArguments(FP->getNumParams(), - ArgsWithoutDependentTypes.size(), - /*PartialOverloading=*/true) || + if (!SemaRef.TooManyArguments(FP->getNumParams(), + ArgsWithoutDependentTypes.size(), + /*PartialOverloading=*/true) || FP->isVariadic()) { if (P) { Results.push_back(ResultCandidate(P)); @@ -6293,8 +6318,8 @@ QualType Sema::ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args, Results.push_back(ResultCandidate(FT)); } } - mergeCandidatesWithResults(*this, Results, CandidateSet, Loc, Args.size()); - QualType ParamType = ProduceSignatureHelp(*this, Results, Args.size(), + mergeCandidatesWithResults(SemaRef, Results, CandidateSet, Loc, Args.size()); + QualType ParamType = ProduceSignatureHelp(SemaRef, Results, Args.size(), OpenParLoc, /*Braced=*/false); return !CandidateSet.empty() ? ParamType : QualType(); } @@ -6366,18 +6391,16 @@ getNextAggregateIndexAfterDesignatedInit(const ResultCandidate &Aggregate, return DesignatedIndex + ArgsAfterDesignator + 1; } -QualType Sema::ProduceConstructorSignatureHelp(QualType Type, - SourceLocation Loc, - ArrayRef Args, - SourceLocation OpenParLoc, - bool Braced) { +QualType SemaCodeCompletion::ProduceConstructorSignatureHelp( + QualType Type, SourceLocation Loc, ArrayRef Args, + SourceLocation OpenParLoc, bool Braced) { if (!CodeCompleter) return QualType(); SmallVector Results; // A complete type is needed to lookup for constructors. RecordDecl *RD = - isCompleteType(Loc, Type) ? Type->getAsRecordDecl() : nullptr; + SemaRef.isCompleteType(Loc, Type) ? Type->getAsRecordDecl() : nullptr; if (!RD) return Type; CXXRecordDecl *CRD = dyn_cast(RD); @@ -6389,7 +6412,7 @@ QualType Sema::ProduceConstructorSignatureHelp(QualType Type, // FIXME: it would be nice to support "unwrapping" aggregates that contain // a single subaggregate, like std::array -> T __elements[N]. if (Braced && !RD->isUnion() && - (!LangOpts.CPlusPlus || (CRD && CRD->isAggregate()))) { + (!getLangOpts().CPlusPlus || (CRD && CRD->isAggregate()))) { ResultCandidate AggregateSig(RD); unsigned AggregateSize = AggregateSig.getNumParams(); @@ -6399,7 +6422,7 @@ QualType Sema::ProduceConstructorSignatureHelp(QualType Type, if (*NextIndex >= AggregateSize) return Type; Results.push_back(AggregateSig); - return ProduceSignatureHelp(*this, Results, *NextIndex, OpenParLoc, + return ProduceSignatureHelp(SemaRef, Results, *NextIndex, OpenParLoc, Braced); } @@ -6413,36 +6436,39 @@ QualType Sema::ProduceConstructorSignatureHelp(QualType Type, if (CRD) { OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); - for (NamedDecl *C : LookupConstructors(CRD)) { + for (NamedDecl *C : SemaRef.LookupConstructors(CRD)) { if (auto *FD = dyn_cast(C)) { // FIXME: we can't yet provide correct signature help for initializer // list constructors, so skip them entirely. - if (Braced && LangOpts.CPlusPlus && isInitListConstructor(FD)) + if (Braced && getLangOpts().CPlusPlus && + SemaRef.isInitListConstructor(FD)) continue; - AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args, - CandidateSet, - /*SuppressUserConversions=*/false, - /*PartialOverloading=*/true, - /*AllowExplicit*/ true); + SemaRef.AddOverloadCandidate( + FD, DeclAccessPair::make(FD, C->getAccess()), Args, CandidateSet, + /*SuppressUserConversions=*/false, + /*PartialOverloading=*/true, + /*AllowExplicit*/ true); } else if (auto *FTD = dyn_cast(C)) { - if (Braced && LangOpts.CPlusPlus && - isInitListConstructor(FTD->getTemplatedDecl())) + if (Braced && getLangOpts().CPlusPlus && + SemaRef.isInitListConstructor(FTD->getTemplatedDecl())) continue; - AddTemplateOverloadCandidate( + SemaRef.AddTemplateOverloadCandidate( FTD, DeclAccessPair::make(FTD, C->getAccess()), /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet, /*SuppressUserConversions=*/false, /*PartialOverloading=*/true); } } - mergeCandidatesWithResults(*this, Results, CandidateSet, Loc, Args.size()); + mergeCandidatesWithResults(SemaRef, Results, CandidateSet, Loc, + Args.size()); } - return ProduceSignatureHelp(*this, Results, Args.size(), OpenParLoc, Braced); + return ProduceSignatureHelp(SemaRef, Results, Args.size(), OpenParLoc, + Braced); } -QualType Sema::ProduceCtorInitMemberSignatureHelp( +QualType SemaCodeCompletion::ProduceCtorInitMemberSignatureHelp( Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy, ArrayRef ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc, bool Braced) { @@ -6454,7 +6480,7 @@ QualType Sema::ProduceCtorInitMemberSignatureHelp( if (!Constructor) return QualType(); // FIXME: Add support for Base class constructors as well. - if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl( + if (ValueDecl *MemberDecl = SemaRef.tryLookupCtorInitMemberDecl( Constructor->getParent(), SS, TemplateTypeTy, II)) return ProduceConstructorSignatureHelp(MemberDecl->getType(), MemberDecl->getLocation(), ArgExprs, @@ -6484,7 +6510,7 @@ static bool argMatchesTemplateParams(const ParsedTemplateArgument &Arg, llvm_unreachable("Unhandled switch case"); } -QualType Sema::ProduceTemplateArgumentSignatureHelp( +QualType SemaCodeCompletion::ProduceTemplateArgumentSignatureHelp( TemplateTy ParsedTemplate, ArrayRef Args, SourceLocation LAngleLoc) { if (!CodeCompleter || !ParsedTemplate) @@ -6512,7 +6538,7 @@ QualType Sema::ProduceTemplateArgumentSignatureHelp( if (const auto *TD = llvm::dyn_cast(ND)) Consider(TD); } - return ProduceSignatureHelp(*this, Results, Args.size(), LAngleLoc, + return ProduceSignatureHelp(SemaRef, Results, Args.size(), LAngleLoc, /*Braced=*/false); } @@ -6541,9 +6567,8 @@ static QualType getDesignatedType(QualType BaseType, const Designation &Desig) { return BaseType; } -void Sema::CodeCompleteDesignator(QualType BaseType, - llvm::ArrayRef InitExprs, - const Designation &D) { +void SemaCodeCompletion::CodeCompleteDesignator( + QualType BaseType, llvm::ArrayRef InitExprs, const Designation &D) { BaseType = getDesignatedType(BaseType, D); if (BaseType.isNull()) return; @@ -6553,7 +6578,7 @@ void Sema::CodeCompleteDesignator(QualType BaseType, CodeCompletionContext CCC(CodeCompletionContext::CCC_DotMemberAccess, BaseType); - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CCC); Results.EnterNewScope(); @@ -6569,14 +6594,15 @@ void Sema::CodeCompleteDesignator(QualType BaseType, // FIXME: Make use of previous designators to mark any fields before those // inaccessible, and also compute the next initializer priority. ResultBuilder::Result Result(FD, Results.getBasePriority(FD)); - Results.AddResult(Result, CurContext, /*Hiding=*/nullptr); + Results.AddResult(Result, SemaRef.CurContext, /*Hiding=*/nullptr); } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { +void SemaCodeCompletion::CodeCompleteInitializer(Scope *S, Decl *D) { ValueDecl *VD = dyn_cast_or_null(D); if (!VD) { CodeCompleteOrdinaryName(S, PCC_Expression); @@ -6591,19 +6617,19 @@ void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { CodeCompleteExpression(S, Data); } -void Sema::CodeCompleteAfterIf(Scope *S, bool IsBracedThen) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteAfterIf(Scope *S, bool IsBracedThen) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), - mapCodeCompletionContext(*this, PCC_Statement)); + mapCodeCompletionContext(SemaRef, PCC_Statement)); Results.setFilter(&ResultBuilder::IsOrdinaryName); Results.EnterNewScope(); - CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals(), - CodeCompleter->loadExternal()); + CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext); + SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); - AddOrdinaryNameResults(PCC_Statement, S, *this, Results); + AddOrdinaryNameResults(PCC_Statement, S, SemaRef, Results); // "else" block CodeCompletionBuilder Builder(Results.getAllocator(), @@ -6649,16 +6675,18 @@ void Sema::CodeCompleteAfterIf(Scope *S, bool IsBracedThen) { AddPrettyFunctionResults(getLangOpts(), Results); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); + AddMacroResults(SemaRef.PP, Results, CodeCompleter->loadExternal(), false); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, - bool EnteringContext, - bool IsUsingDeclaration, QualType BaseType, - QualType PreferredType) { +void SemaCodeCompletion::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, + bool EnteringContext, + bool IsUsingDeclaration, + QualType BaseType, + QualType PreferredType) { if (SS.isEmpty() || !CodeCompleter) return; @@ -6674,34 +6702,34 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, // As SS is invalid, we try to collect accessible contexts from the current // scope with a dummy lookup so that the completion consumer can try to // guess what the specified scope is. - ResultBuilder DummyResults(*this, CodeCompleter->getAllocator(), + ResultBuilder DummyResults(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CC); if (!PreferredType.isNull()) DummyResults.setPreferredType(PreferredType); if (S->getEntity()) { CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(), BaseType); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - /*IncludeGlobalScope=*/false, - /*LoadExternal=*/false); + SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer, + /*IncludeGlobalScope=*/false, + /*LoadExternal=*/false); } - HandleCodeCompleteResults(this, CodeCompleter, + HandleCodeCompleteResults(&SemaRef, CodeCompleter, DummyResults.getCompletionContext(), nullptr, 0); return; } // Always pretend to enter a context to ensure that a dependent type // resolves to a dependent record. - DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true); + DeclContext *Ctx = SemaRef.computeDeclContext(SS, /*EnteringContext=*/true); // Try to instantiate any non-dependent declaration contexts before // we look in them. Bail out if we fail. NestedNameSpecifier *NNS = SS.getScopeRep(); if (NNS != nullptr && SS.isValid() && !NNS->isDependent()) { - if (Ctx == nullptr || RequireCompleteDeclContext(SS, Ctx)) + if (Ctx == nullptr || SemaRef.RequireCompleteDeclContext(SS, Ctx)) return; } - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CC); if (!PreferredType.isNull()) Results.setPreferredType(PreferredType); @@ -6722,7 +6750,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, if (R.Operator != ConceptInfo::Member::Colons) continue; Results.AddResult(CodeCompletionResult( - R.render(*this, CodeCompleter->getAllocator(), + R.render(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo()))); } } @@ -6734,23 +6762,24 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, // in a context that permits expressions. This is a general issue with // qualified-id completions. if (Ctx && !EnteringContext) - MaybeAddOverrideCalls(*this, Ctx, Results); + MaybeAddOverrideCalls(SemaRef, Ctx, Results); Results.ExitScope(); if (Ctx && (CodeCompleter->includeNamespaceLevelDecls() || !Ctx->isFileContext())) { CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType); - LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer, - /*IncludeGlobalScope=*/true, - /*IncludeDependentBases=*/true, - CodeCompleter->loadExternal()); + SemaRef.LookupVisibleDecls(Ctx, Sema::LookupOrdinaryName, Consumer, + /*IncludeGlobalScope=*/true, + /*IncludeDependentBases=*/true, + CodeCompleter->loadExternal()); } - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteUsing(Scope *S) { +void SemaCodeCompletion::CodeCompleteUsing(Scope *S) { if (!CodeCompleter) return; @@ -6759,7 +6788,7 @@ void Sema::CodeCompleteUsing(Scope *S) { CodeCompletionContext Context(CodeCompletionContext::CCC_SymbolOrNewName); Context.setIsUsingDeclaration(true); - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), Context, &ResultBuilder::IsNestedNameSpecifier); Results.EnterNewScope(); @@ -6770,48 +6799,50 @@ void Sema::CodeCompleteUsing(Scope *S) { // After "using", we can see anything that would start a // nested-name-specifier. - CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals(), - CodeCompleter->loadExternal()); + CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext); + SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteUsingDirective(Scope *S) { +void SemaCodeCompletion::CodeCompleteUsingDirective(Scope *S) { if (!CodeCompleter) return; // After "using namespace", we expect to see a namespace name or namespace // alias. - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Namespace, &ResultBuilder::IsNamespaceOrAlias); Results.EnterNewScope(); - CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals(), - CodeCompleter->loadExternal()); + CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext); + SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteNamespaceDecl(Scope *S) { +void SemaCodeCompletion::CodeCompleteNamespaceDecl(Scope *S) { if (!CodeCompleter) return; DeclContext *Ctx = S->getEntity(); if (!S->getParent()) - Ctx = Context.getTranslationUnitDecl(); + Ctx = getASTContext().getTranslationUnitDecl(); bool SuppressedGlobalResults = Ctx && !CodeCompleter->includeGlobals() && isa(Ctx); - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), SuppressedGlobalResults ? CodeCompletionContext::CCC_Namespace @@ -6840,37 +6871,39 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { Results.AddResult( CodeCompletionResult(NS->second, Results.getBasePriority(NS->second), nullptr), - CurContext, nullptr, false); + SemaRef.CurContext, nullptr, false); Results.ExitScope(); } - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { +void SemaCodeCompletion::CodeCompleteNamespaceAliasDecl(Scope *S) { if (!CodeCompleter) return; // After "namespace", we expect to see a namespace or alias. - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Namespace, &ResultBuilder::IsNamespaceOrAlias); - CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals(), - CodeCompleter->loadExternal()); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext); + SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteOperatorName(Scope *S) { +void SemaCodeCompletion::CodeCompleteOperatorName(Scope *S) { if (!CodeCompleter) return; typedef CodeCompletionResult Result; - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Type, &ResultBuilder::IsType); @@ -6885,31 +6918,32 @@ void Sema::CodeCompleteOperatorName(Scope *S) { // Add any type names visible from the current scope Results.allowNestedNameSpecifiers(); - CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals(), - CodeCompleter->loadExternal()); + CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext); + SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); // Add any type specifiers AddTypeSpecifierResults(getLangOpts(), Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteConstructorInitializer( +void SemaCodeCompletion::CodeCompleteConstructorInitializer( Decl *ConstructorD, ArrayRef Initializers) { if (!ConstructorD) return; - AdjustDeclIfTemplate(ConstructorD); + SemaRef.AdjustDeclIfTemplate(ConstructorD); auto *Constructor = dyn_cast(ConstructorD); if (!Constructor) return; - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Symbol); Results.EnterNewScope(); @@ -6919,7 +6953,7 @@ void Sema::CodeCompleteConstructorInitializer( llvm::SmallPtrSet InitializedBases; for (unsigned I = 0, E = Initializers.size(); I != E; ++I) { if (Initializers[I]->isBaseInitializer()) - InitializedBases.insert(Context.getCanonicalType( + InitializedBases.insert(getASTContext().getCanonicalType( QualType(Initializers[I]->getBaseClass(), 0))); else InitializedFields.insert( @@ -6927,7 +6961,7 @@ void Sema::CodeCompleteConstructorInitializer( } // Add completions for base classes. - PrintingPolicy Policy = getCompletionPrintingPolicy(*this); + PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef); bool SawLastInitializer = Initializers.empty(); CXXRecordDecl *ClassDecl = Constructor->getParent(); @@ -6937,10 +6971,10 @@ void Sema::CodeCompleteConstructorInitializer( Builder.AddTypedTextChunk(Name); Builder.AddChunk(CodeCompletionString::CK_LeftParen); if (const auto *Function = dyn_cast(ND)) - AddFunctionParameterChunks(PP, Policy, Function, Builder); + AddFunctionParameterChunks(SemaRef.PP, Policy, Function, Builder); else if (const auto *FunTemplDecl = dyn_cast(ND)) - AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(), - Builder); + AddFunctionParameterChunks(SemaRef.PP, Policy, + FunTemplDecl->getTemplatedDecl(), Builder); Builder.AddChunk(CodeCompletionString::CK_RightParen); return Builder.TakeString(); }; @@ -6972,7 +7006,7 @@ void Sema::CodeCompleteConstructorInitializer( FD->getType().getAsString(Policy)) : Name, FD); - auto Ctors = getConstructors(Context, RD); + auto Ctors = getConstructors(getASTContext(), RD); if (Ctors.begin() == Ctors.end()) return AddDefaultCtorInit(Name, Name, RD); for (const NamedDecl *Ctor : Ctors) { @@ -6999,11 +7033,12 @@ void Sema::CodeCompleteConstructorInitializer( }; for (const auto &Base : ClassDecl->bases()) { - if (!InitializedBases.insert(Context.getCanonicalType(Base.getType())) + if (!InitializedBases + .insert(getASTContext().getCanonicalType(Base.getType())) .second) { SawLastInitializer = !Initializers.empty() && Initializers.back()->isBaseInitializer() && - Context.hasSameUnqualifiedType( + getASTContext().hasSameUnqualifiedType( Base.getType(), QualType(Initializers.back()->getBaseClass(), 0)); continue; } @@ -7014,11 +7049,12 @@ void Sema::CodeCompleteConstructorInitializer( // Add completions for virtual base classes. for (const auto &Base : ClassDecl->vbases()) { - if (!InitializedBases.insert(Context.getCanonicalType(Base.getType())) + if (!InitializedBases + .insert(getASTContext().getCanonicalType(Base.getType())) .second) { SawLastInitializer = !Initializers.empty() && Initializers.back()->isBaseInitializer() && - Context.hasSameUnqualifiedType( + getASTContext().hasSameUnqualifiedType( Base.getType(), QualType(Initializers.back()->getBaseClass(), 0)); continue; } @@ -7045,8 +7081,9 @@ void Sema::CodeCompleteConstructorInitializer( } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } /// Determine whether this scope denotes a namespace. @@ -7058,9 +7095,10 @@ static bool isNamespaceScope(Scope *S) { return DC->isFileContext(); } -void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, - bool AfterAmpersand) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteLambdaIntroducer(Scope *S, + LambdaIntroducer &Intro, + bool AfterAmpersand) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); @@ -7086,24 +7124,25 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, if (Known.insert(Var->getIdentifier()).second) Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration), - CurContext, nullptr, false); + SemaRef.CurContext, nullptr, false); } } // Add 'this', if it would be valid. if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy) - addThisCompletion(*this, Results); + addThisCompletion(SemaRef, Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteAfterFunctionEquals(Declarator &D) { - if (!LangOpts.CPlusPlus11) +void SemaCodeCompletion::CodeCompleteAfterFunctionEquals(Declarator &D) { + if (!getLangOpts().CPlusPlus11) return; - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); auto ShouldAddDefault = [&D, this]() { @@ -7123,7 +7162,7 @@ void Sema::CodeCompleteAfterFunctionEquals(Declarator &D) { // verify that it is the copy or move assignment? if (Op == OverloadedOperatorKind::OO_Equal) return true; - if (LangOpts.CPlusPlus20 && + if (getLangOpts().CPlusPlus20 && (Op == OverloadedOperatorKind::OO_EqualEqual || Op == OverloadedOperatorKind::OO_ExclaimEqual || Op == OverloadedOperatorKind::OO_Less || @@ -7143,8 +7182,9 @@ void Sema::CodeCompleteAfterFunctionEquals(Declarator &D) { // first function declaration. Results.AddResult("delete"); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } /// Macro that optionally prepends an "@" to the string literal passed in via @@ -7244,20 +7284,21 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { } } -void Sema::CodeCompleteObjCAtDirective(Scope *S) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteObjCAtDirective(Scope *S) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); - if (isa(CurContext)) + if (isa(SemaRef.CurContext)) AddObjCImplementationResults(getLangOpts(), Results, false); - else if (CurContext->isObjCContainer()) + else if (SemaRef.CurContext->isObjCContainer()) AddObjCInterfaceResults(getLangOpts(), Results, false); else AddObjCTopLevelResults(Results, false); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { @@ -7381,38 +7422,41 @@ static void AddObjCVisibilityResults(const LangOptions &LangOpts, Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package"))); } -void Sema::CodeCompleteObjCAtVisibility(Scope *S) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteObjCAtVisibility(Scope *S) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); AddObjCVisibilityResults(getLangOpts(), Results, false); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCAtStatement(Scope *S) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteObjCAtStatement(Scope *S) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); AddObjCStatementResults(Results, false); AddObjCExpressionResults(Results, false); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCAtExpression(Scope *S) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteObjCAtExpression(Scope *S) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); AddObjCExpressionResults(Results, false); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } /// Determine whether the addition of the given flag to an Objective-C @@ -7448,13 +7492,14 @@ static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) { return false; } -void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { +void SemaCodeCompletion::CodeCompleteObjCPropertyFlags(Scope *S, + ObjCDeclSpec &ODS) { if (!CodeCompleter) return; unsigned Attributes = ODS.getPropertyAttributes(); - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); @@ -7517,8 +7562,9 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { Results.AddResult(CodeCompletionResult("null_resettable")); } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } /// Describes the kind of Objective-C method that we want to find @@ -7677,12 +7723,13 @@ static void AddObjCMethods(ObjCContainerDecl *Container, IsRootClass); } -void Sema::CodeCompleteObjCPropertyGetter(Scope *S) { +void SemaCodeCompletion::CodeCompleteObjCPropertyGetter(Scope *S) { // Try to find the interface where getters might live. - ObjCInterfaceDecl *Class = dyn_cast_or_null(CurContext); + ObjCInterfaceDecl *Class = + dyn_cast_or_null(SemaRef.CurContext); if (!Class) { if (ObjCCategoryDecl *Category = - dyn_cast_or_null(CurContext)) + dyn_cast_or_null(SemaRef.CurContext)) Class = Category->getClassInterface(); if (!Class) @@ -7690,26 +7737,28 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S) { } // Find all of the potential getters. - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); VisitedSelectorSet Selectors; - AddObjCMethods(Class, true, MK_ZeroArgSelector, std::nullopt, CurContext, - Selectors, + AddObjCMethods(Class, true, MK_ZeroArgSelector, std::nullopt, + SemaRef.CurContext, Selectors, /*AllowSameLength=*/true, Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCPropertySetter(Scope *S) { +void SemaCodeCompletion::CodeCompleteObjCPropertySetter(Scope *S) { // Try to find the interface where setters might live. - ObjCInterfaceDecl *Class = dyn_cast_or_null(CurContext); + ObjCInterfaceDecl *Class = + dyn_cast_or_null(SemaRef.CurContext); if (!Class) { if (ObjCCategoryDecl *Category = - dyn_cast_or_null(CurContext)) + dyn_cast_or_null(SemaRef.CurContext)) Class = Category->getClassInterface(); if (!Class) @@ -7717,24 +7766,25 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S) { } // Find all of the potential getters. - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); VisitedSelectorSet Selectors; - AddObjCMethods(Class, true, MK_OneArgSelector, std::nullopt, CurContext, - Selectors, + AddObjCMethods(Class, true, MK_OneArgSelector, std::nullopt, + SemaRef.CurContext, Selectors, /*AllowSameLength=*/true, Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, - bool IsParameter) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, + bool IsParameter) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Type); Results.EnterNewScope(); @@ -7771,7 +7821,7 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, // an action, e.g., // IBAction)<#selector#>:(id)sender if (DS.getObjCDeclQualifier() == 0 && !IsParameter && - PP.isMacroDefined("IBAction")) { + SemaRef.PP.isMacroDefined("IBAction")) { CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo(), CCP_CodePattern, CXAvailability_Available); @@ -7792,21 +7842,22 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, } // Add various builtin type names and specifiers. - AddOrdinaryNameResults(PCC_Type, S, *this, Results); + AddOrdinaryNameResults(PCC_Type, S, SemaRef, Results); Results.ExitScope(); // Add the various type names Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName); - CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals(), - CodeCompleter->loadExternal()); + CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext); + SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); + AddMacroResults(SemaRef.PP, Results, CodeCompleter->loadExternal(), false); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } /// When we have an expression with type "id", we may assume @@ -7997,49 +8048,50 @@ AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword, return SuperMethod; } -void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { +void SemaCodeCompletion::CodeCompleteObjCMessageReceiver(Scope *S) { typedef CodeCompletionResult Result; ResultBuilder Results( - *this, CodeCompleter->getAllocator(), + SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCMessageReceiver, getLangOpts().CPlusPlus11 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture : &ResultBuilder::IsObjCMessageReceiver); - CodeCompletionDeclConsumer Consumer(Results, CurContext); + CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext); Results.EnterNewScope(); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals(), - CodeCompleter->loadExternal()); + SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); // If we are in an Objective-C method inside a class that has a superclass, // add "super" as an option. - if (ObjCMethodDecl *Method = getCurMethodDecl()) + if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) if (ObjCInterfaceDecl *Iface = Method->getClassInterface()) if (Iface->getSuperClass()) { Results.AddResult(Result("super")); - AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, std::nullopt, + AddSuperSendCompletion(SemaRef, /*NeedSuperKeyword=*/true, std::nullopt, Results); } if (getLangOpts().CPlusPlus11) - addThisCompletion(*this, Results); + addThisCompletion(SemaRef, Results); Results.ExitScope(); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + AddMacroResults(SemaRef.PP, Results, CodeCompleter->loadExternal(), false); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCSuperMessage( +void SemaCodeCompletion::CodeCompleteObjCSuperMessage( Scope *S, SourceLocation SuperLoc, ArrayRef SelIdents, bool AtArgumentExpression) { ObjCInterfaceDecl *CDecl = nullptr; - if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { + if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl()) { // Figure out which interface we're in. CDecl = CurMethod->getClassInterface(); if (!CDecl) @@ -8062,13 +8114,14 @@ void Sema::CodeCompleteObjCSuperMessage( } else { // "super" may be the name of a type or variable. Figure out which // it is. - const IdentifierInfo *Super = getSuperIdentifier(); - NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName); + const IdentifierInfo *Super = SemaRef.getSuperIdentifier(); + NamedDecl *ND = + SemaRef.LookupSingleName(S, Super, SuperLoc, Sema::LookupOrdinaryName); if ((CDecl = dyn_cast_or_null(ND))) { // "super" names an interface. Use it. } else if (TypeDecl *TD = dyn_cast_or_null(ND)) { if (const ObjCObjectType *Iface = - Context.getTypeDeclType(TD)->getAs()) + getASTContext().getTypeDeclType(TD)->getAs()) CDecl = Iface->getInterface(); } else if (ND && isa(ND)) { // "super" names an unresolved type; we can't be more specific. @@ -8078,9 +8131,10 @@ void Sema::CodeCompleteObjCSuperMessage( SourceLocation TemplateKWLoc; UnqualifiedId id; id.setIdentifier(Super, SuperLoc); - ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id, - /*HasTrailingLParen=*/false, - /*IsAddressOfOperand=*/false); + ExprResult SuperExpr = + SemaRef.ActOnIdExpression(S, SS, TemplateKWLoc, id, + /*HasTrailingLParen=*/false, + /*IsAddressOfOperand=*/false); return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(), SelIdents, AtArgumentExpression); } @@ -8090,7 +8144,7 @@ void Sema::CodeCompleteObjCSuperMessage( ParsedType Receiver; if (CDecl) - Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl)); + Receiver = ParsedType::make(getASTContext().getObjCInterfaceType(CDecl)); return CodeCompleteObjCClassMessage(S, Receiver, SelIdents, AtArgumentExpression, /*IsSuper=*/true); @@ -8206,19 +8260,19 @@ AddClassMessageCompletions(Sema &SemaRef, Scope *S, ParsedType Receiver, Results.ExitScope(); } -void Sema::CodeCompleteObjCClassMessage( +void SemaCodeCompletion::CodeCompleteObjCClassMessage( Scope *S, ParsedType Receiver, ArrayRef SelIdents, bool AtArgumentExpression, bool IsSuper) { - QualType T = this->GetTypeFromParser(Receiver); + QualType T = SemaRef.GetTypeFromParser(Receiver); ResultBuilder Results( - *this, CodeCompleter->getAllocator(), + SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T, SelIdents)); - AddClassMessageCompletions(*this, S, Receiver, SelIdents, + AddClassMessageCompletions(SemaRef, S, Receiver, SelIdents, AtArgumentExpression, IsSuper, Results); // If we're actually at the argument expression (rather than prior to the @@ -8236,21 +8290,23 @@ void Sema::CodeCompleteObjCClassMessage( return; } - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCInstanceMessage( +void SemaCodeCompletion::CodeCompleteObjCInstanceMessage( Scope *S, Expr *Receiver, ArrayRef SelIdents, bool AtArgumentExpression, ObjCInterfaceDecl *Super) { typedef CodeCompletionResult Result; + ASTContext &Context = getASTContext(); Expr *RecExpr = static_cast(Receiver); // If necessary, apply function/array conversion to the receiver. // C99 6.7.5.3p[7,8]. if (RecExpr) { - ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr); + ExprResult Conv = SemaRef.DefaultFunctionArrayLvalueConversion(RecExpr); if (Conv.isInvalid()) // conversion failed. bail. return; RecExpr = Conv.get(); @@ -8275,7 +8331,7 @@ void Sema::CodeCompleteObjCInstanceMessage( Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace)); } } else if (RecExpr && getLangOpts().CPlusPlus) { - ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr); + ExprResult Conv = SemaRef.PerformContextuallyConvertToObjCPointer(RecExpr); if (Conv.isUsable()) { RecExpr = Conv.get(); ReceiverType = RecExpr->getType(); @@ -8284,7 +8340,7 @@ void Sema::CodeCompleteObjCInstanceMessage( // Build the set of methods we can see. ResultBuilder Results( - *this, CodeCompleter->getAllocator(), + SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage, ReceiverType, SelIdents)); @@ -8295,13 +8351,13 @@ void Sema::CodeCompleteObjCInstanceMessage( // completion. if (Super) { if (ObjCMethodDecl *SuperMethod = - AddSuperSendCompletion(*this, false, SelIdents, Results)) + AddSuperSendCompletion(SemaRef, false, SelIdents, Results)) Results.Ignore(SuperMethod); } // If we're inside an Objective-C method definition, prefer its selector to // others. - if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) + if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl()) Results.setPreferredSelector(CurMethod->getSelector()); // Keep track of the selectors we've already added. @@ -8312,9 +8368,9 @@ void Sema::CodeCompleteObjCInstanceMessage( // class method. if (ReceiverType->isObjCClassType() || ReceiverType->isObjCQualifiedClassType()) { - if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { + if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl()) { if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface()) - AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext, + AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, SemaRef.CurContext, Selectors, AtArgumentExpression, Results); } } @@ -8323,7 +8379,7 @@ void Sema::CodeCompleteObjCInstanceMessage( ReceiverType->getAsObjCQualifiedIdType()) { // Search protocols for instance methods. for (auto *I : QualID->quals()) - AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors, + AddObjCMethods(I, true, MK_Any, SelIdents, SemaRef.CurContext, Selectors, AtArgumentExpression, Results); } // Handle messages to a pointer to interface type. @@ -8331,11 +8387,12 @@ void Sema::CodeCompleteObjCInstanceMessage( ReceiverType->getAsObjCInterfacePointerType()) { // Search the class, its superclasses, etc., for instance methods. AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents, - CurContext, Selectors, AtArgumentExpression, Results); + SemaRef.CurContext, Selectors, AtArgumentExpression, + Results); // Search protocols for instance methods. for (auto *I : IFacePtr->quals()) - AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors, + AddObjCMethods(I, true, MK_Any, SelIdents, SemaRef.CurContext, Selectors, AtArgumentExpression, Results); } // Handle messages to "id". @@ -8345,19 +8402,21 @@ void Sema::CodeCompleteObjCInstanceMessage( // If we have an external source, load the entire class method // pool from the AST file. - if (ExternalSource) { - for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); + if (SemaRef.ExternalSource) { + for (uint32_t I = 0, + N = SemaRef.ExternalSource->GetNumExternalSelectors(); I != N; ++I) { - Selector Sel = ExternalSource->GetExternalSelector(I); - if (Sel.isNull() || ObjC().MethodPool.count(Sel)) + Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I); + if (Sel.isNull() || SemaRef.ObjC().MethodPool.count(Sel)) continue; - ObjC().ReadMethodPool(Sel); + SemaRef.ObjC().ReadMethodPool(Sel); } } - for (SemaObjC::GlobalMethodPool::iterator M = ObjC().MethodPool.begin(), - MEnd = ObjC().MethodPool.end(); + for (SemaObjC::GlobalMethodPool::iterator + M = SemaRef.ObjC().MethodPool.begin(), + MEnd = SemaRef.ObjC().MethodPool.end(); M != MEnd; ++M) { for (ObjCMethodList *MethList = &M->second.first; MethList && MethList->getMethod(); MethList = MethList->getNext()) { @@ -8371,7 +8430,7 @@ void Sema::CodeCompleteObjCInstanceMessage( Results.getBasePriority(MethList->getMethod()), nullptr); R.StartParameter = SelIdents.size(); R.AllParametersAreInformative = false; - Results.MaybeAddResult(R, CurContext); + Results.MaybeAddResult(R, SemaRef.CurContext); } } } @@ -8392,12 +8451,13 @@ void Sema::CodeCompleteObjCInstanceMessage( return; } - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCForCollection(Scope *S, - DeclGroupPtrTy IterationVar) { +void SemaCodeCompletion::CodeCompleteObjCForCollection( + Scope *S, DeclGroupPtrTy IterationVar) { CodeCompleteExpressionData Data; Data.ObjCCollection = true; @@ -8412,27 +8472,28 @@ void Sema::CodeCompleteObjCForCollection(Scope *S, CodeCompleteExpression(S, Data); } -void Sema::CodeCompleteObjCSelector( +void SemaCodeCompletion::CodeCompleteObjCSelector( Scope *S, ArrayRef SelIdents) { // If we have an external source, load the entire class method // pool from the AST file. - if (ExternalSource) { - for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; - ++I) { - Selector Sel = ExternalSource->GetExternalSelector(I); - if (Sel.isNull() || ObjC().MethodPool.count(Sel)) + if (SemaRef.ExternalSource) { + for (uint32_t I = 0, N = SemaRef.ExternalSource->GetNumExternalSelectors(); + I != N; ++I) { + Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I); + if (Sel.isNull() || SemaRef.ObjC().MethodPool.count(Sel)) continue; - ObjC().ReadMethodPool(Sel); + SemaRef.ObjC().ReadMethodPool(Sel); } } - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_SelectorName); Results.EnterNewScope(); - for (SemaObjC::GlobalMethodPool::iterator M = ObjC().MethodPool.begin(), - MEnd = ObjC().MethodPool.end(); + for (SemaObjC::GlobalMethodPool::iterator + M = SemaRef.ObjC().MethodPool.begin(), + MEnd = SemaRef.ObjC().MethodPool.end(); M != MEnd; ++M) { Selector Sel = M->first; @@ -8466,8 +8527,9 @@ void Sema::CodeCompleteObjCSelector( } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } /// Add all of the protocol declarations that we find in the given @@ -8487,9 +8549,9 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, } } -void Sema::CodeCompleteObjCProtocolReferences( +void SemaCodeCompletion::CodeCompleteObjCProtocolReferences( ArrayRef Protocols) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCProtocolName); @@ -8501,22 +8563,23 @@ void Sema::CodeCompleteObjCProtocolReferences( // FIXME: This doesn't work when caching code-completion results. for (const IdentifierLocPair &Pair : Protocols) if (ObjCProtocolDecl *Protocol = - ObjC().LookupProtocol(Pair.first, Pair.second)) + SemaRef.ObjC().LookupProtocol(Pair.first, Pair.second)) Results.Ignore(Protocol); // Add all protocols. - AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false, - Results); + AddProtocolResults(getASTContext().getTranslationUnitDecl(), + SemaRef.CurContext, false, Results); Results.ExitScope(); } - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCProtocolDecl(Scope *) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteObjCProtocolDecl(Scope *) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCProtocolName); @@ -8524,14 +8587,15 @@ void Sema::CodeCompleteObjCProtocolDecl(Scope *) { Results.EnterNewScope(); // Add all protocols. - AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true, - Results); + AddProtocolResults(getASTContext().getTranslationUnitDecl(), + SemaRef.CurContext, true, Results); Results.ExitScope(); } - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } /// Add all of the Objective-C interface declarations that we find in @@ -8553,99 +8617,102 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, } } -void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteObjCInterfaceDecl(Scope *S) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCInterfaceName); Results.EnterNewScope(); if (CodeCompleter->includeGlobals()) { // Add all classes. - AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, - false, Results); + AddInterfaceResults(getASTContext().getTranslationUnitDecl(), + SemaRef.CurContext, false, false, Results); } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCClassForwardDecl(Scope *S) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteObjCClassForwardDecl(Scope *S) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCClassForwardDecl); Results.EnterNewScope(); if (CodeCompleter->includeGlobals()) { // Add all classes. - AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, - false, Results); + AddInterfaceResults(getASTContext().getTranslationUnitDecl(), + SemaRef.CurContext, false, false, Results); } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, - SourceLocation ClassNameLoc) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteObjCSuperclass( + Scope *S, IdentifierInfo *ClassName, SourceLocation ClassNameLoc) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCInterfaceName); Results.EnterNewScope(); // Make sure that we ignore the class we're currently defining. - NamedDecl *CurClass = - LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); + NamedDecl *CurClass = SemaRef.LookupSingleName( + SemaRef.TUScope, ClassName, ClassNameLoc, Sema::LookupOrdinaryName); if (CurClass && isa(CurClass)) Results.Ignore(CurClass); if (CodeCompleter->includeGlobals()) { // Add all classes. - AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, - false, Results); + AddInterfaceResults(getASTContext().getTranslationUnitDecl(), + SemaRef.CurContext, false, false, Results); } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCImplementationDecl(Scope *S) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteObjCImplementationDecl(Scope *S) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCImplementation); Results.EnterNewScope(); if (CodeCompleter->includeGlobals()) { // Add all unimplemented classes. - AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, - true, Results); + AddInterfaceResults(getASTContext().getTranslationUnitDecl(), + SemaRef.CurContext, false, true, Results); } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, - IdentifierInfo *ClassName, - SourceLocation ClassNameLoc) { +void SemaCodeCompletion::CodeCompleteObjCInterfaceCategory( + Scope *S, IdentifierInfo *ClassName, SourceLocation ClassNameLoc) { typedef CodeCompletionResult Result; - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCCategoryName); // Ignore any categories we find that have already been implemented by this // interface. llvm::SmallPtrSet CategoryNames; - NamedDecl *CurClass = - LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); + NamedDecl *CurClass = SemaRef.LookupSingleName( + SemaRef.TUScope, ClassName, ClassNameLoc, Sema::LookupOrdinaryName); if (ObjCInterfaceDecl *Class = dyn_cast_or_null(CurClass)) { for (const auto *Cat : Class->visible_categories()) @@ -8654,34 +8721,34 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, // Add all of the categories we know about. Results.EnterNewScope(); - TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); + TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl(); for (const auto *D : TU->decls()) if (const auto *Category = dyn_cast(D)) if (CategoryNames.insert(Category->getIdentifier()).second) Results.AddResult( Result(Category, Results.getBasePriority(Category), nullptr), - CurContext, nullptr, false); + SemaRef.CurContext, nullptr, false); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCImplementationCategory(Scope *S, - IdentifierInfo *ClassName, - SourceLocation ClassNameLoc) { +void SemaCodeCompletion::CodeCompleteObjCImplementationCategory( + Scope *S, IdentifierInfo *ClassName, SourceLocation ClassNameLoc) { typedef CodeCompletionResult Result; // Find the corresponding interface. If we couldn't find the interface, the // program itself is ill-formed. However, we'll try to be helpful still by // providing the list of all of the categories we know about. - NamedDecl *CurClass = - LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); + NamedDecl *CurClass = SemaRef.LookupSingleName( + SemaRef.TUScope, ClassName, ClassNameLoc, Sema::LookupOrdinaryName); ObjCInterfaceDecl *Class = dyn_cast_or_null(CurClass); if (!Class) return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc); - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCCategoryName); @@ -8696,7 +8763,7 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, if ((!IgnoreImplemented || !Cat->getImplementation()) && CategoryNames.insert(Cat->getIdentifier()).second) Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr), - CurContext, nullptr, false); + SemaRef.CurContext, nullptr, false); } Class = Class->getSuperClass(); @@ -8704,18 +8771,19 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { +void SemaCodeCompletion::CodeCompleteObjCPropertyDefinition(Scope *S) { CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other); - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CCContext); // Figure out where this @synthesize lives. ObjCContainerDecl *Container = - dyn_cast_or_null(CurContext); + dyn_cast_or_null(SemaRef.CurContext); if (!Container || (!isa(Container) && !isa(Container))) return; @@ -8732,29 +8800,30 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { if (ObjCImplementationDecl *ClassImpl = dyn_cast(Container)) AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false, - /*AllowNullaryMethods=*/false, CurContext, + /*AllowNullaryMethods=*/false, SemaRef.CurContext, AddedProperties, Results); else AddObjCProperties(CCContext, cast(Container)->getCategoryDecl(), - false, /*AllowNullaryMethods=*/false, CurContext, + false, /*AllowNullaryMethods=*/false, SemaRef.CurContext, AddedProperties, Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCPropertySynthesizeIvar( +void SemaCodeCompletion::CodeCompleteObjCPropertySynthesizeIvar( Scope *S, IdentifierInfo *PropertyName) { typedef CodeCompletionResult Result; - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); // Figure out where this @synthesize lives. ObjCContainerDecl *Container = - dyn_cast_or_null(CurContext); + dyn_cast_or_null(SemaRef.CurContext); if (!Container || (!isa(Container) && !isa(Container))) return; @@ -8770,7 +8839,7 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar( ->getClassInterface(); // Determine the type of the property we're synthesizing. - QualType PropertyType = Context.getObjCIdType(); + QualType PropertyType = getASTContext().getObjCIdType(); if (Class) { if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration( PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { @@ -8794,7 +8863,7 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar( for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar; Ivar = Ivar->getNextIvar()) { Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr), - CurContext, nullptr, false); + SemaRef.CurContext, nullptr, false); // Determine whether we've seen an ivar with a name similar to the // property. @@ -8823,9 +8892,9 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar( CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(), Priority, CXAvailability_Available); - PrintingPolicy Policy = getCompletionPrintingPolicy(*this); - Builder.AddResultTypeChunk( - GetCompletionTypeString(PropertyType, Context, Policy, Allocator)); + PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef); + Builder.AddResultTypeChunk(GetCompletionTypeString( + PropertyType, getASTContext(), Policy, Allocator)); Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix)); Results.AddResult( Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl)); @@ -8833,8 +8902,9 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar( Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } // Mapping from selectors to the methods that implement that selector, along @@ -9573,15 +9643,15 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, } } -void Sema::CodeCompleteObjCMethodDecl(Scope *S, - std::optional IsInstanceMethod, - ParsedType ReturnTy) { +void SemaCodeCompletion::CodeCompleteObjCMethodDecl( + Scope *S, std::optional IsInstanceMethod, ParsedType ReturnTy) { + ASTContext &Context = getASTContext(); // Determine the return type of the method we're declaring, if // provided. - QualType ReturnType = GetTypeFromParser(ReturnTy); + QualType ReturnType = SemaRef.GetTypeFromParser(ReturnTy); Decl *IDecl = nullptr; - if (CurContext->isObjCContainer()) { - ObjCContainerDecl *OCD = dyn_cast(CurContext); + if (SemaRef.CurContext->isObjCContainer()) { + ObjCContainerDecl *OCD = dyn_cast(SemaRef.CurContext); IDecl = OCD; } // Determine where we should start searching for methods. @@ -9605,7 +9675,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, } if (!SearchDecl) { - HandleCodeCompleteResults(this, CodeCompleter, + HandleCodeCompleteResults(&SemaRef, CodeCompleter, CodeCompletionContext::CCC_Other, nullptr, 0); return; } @@ -9617,11 +9687,11 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, // Add declarations or definitions for each of the known methods. typedef CodeCompletionResult Result; - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); - PrintingPolicy Policy = getCompletionPrintingPolicy(*this); + PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef); for (KnownMethodsMap::iterator M = KnownMethods.begin(), MEnd = KnownMethods.end(); M != MEnd; ++M) { @@ -9746,38 +9816,41 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteObjCMethodDeclSelector( +void SemaCodeCompletion::CodeCompleteObjCMethodDeclSelector( Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy, ArrayRef SelIdents) { // If we have an external source, load the entire class method // pool from the AST file. - if (ExternalSource) { - for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; - ++I) { - Selector Sel = ExternalSource->GetExternalSelector(I); - if (Sel.isNull() || ObjC().MethodPool.count(Sel)) + if (SemaRef.ExternalSource) { + for (uint32_t I = 0, N = SemaRef.ExternalSource->GetNumExternalSelectors(); + I != N; ++I) { + Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I); + if (Sel.isNull() || SemaRef.ObjC().MethodPool.count(Sel)) continue; - ObjC().ReadMethodPool(Sel); + SemaRef.ObjC().ReadMethodPool(Sel); } } // Build the set of methods we can see. typedef CodeCompletionResult Result; - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); if (ReturnTy) - Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType()); + Results.setPreferredType( + SemaRef.GetTypeFromParser(ReturnTy).getNonReferenceType()); Results.EnterNewScope(); - for (SemaObjC::GlobalMethodPool::iterator M = ObjC().MethodPool.begin(), - MEnd = ObjC().MethodPool.end(); + for (SemaObjC::GlobalMethodPool::iterator + M = SemaRef.ObjC().MethodPool.begin(), + MEnd = SemaRef.ObjC().MethodPool.end(); M != MEnd; ++M) { for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first : &M->second.second; @@ -9809,7 +9882,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector( R.StartParameter = SelIdents.size(); R.AllParametersAreInformative = false; R.DeclaringEntity = true; - Results.MaybeAddResult(R, CurContext); + Results.MaybeAddResult(R, SemaRef.CurContext); } } @@ -9817,7 +9890,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector( if (!AtParameterName && !SelIdents.empty() && SelIdents.front()->getName().starts_with("init")) { - for (const auto &M : PP.macros()) { + for (const auto &M : SemaRef.PP.macros()) { if (M.first->getName() != "NS_DESIGNATED_INITIALIZER") continue; Results.EnterNewScope(); @@ -9831,12 +9904,13 @@ void Sema::CodeCompleteObjCMethodDeclSelector( } } - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompletePreprocessorDirective(bool InConditional) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompletePreprocessorDirective(bool InConditional) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_PreprocessorDirective); Results.EnterNewScope(); @@ -10001,17 +10075,20 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { // FIXME: we don't support #assert or #unassert, so don't suggest them. Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) { - CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction - : Sema::PCC_Namespace); +void SemaCodeCompletion::CodeCompleteInPreprocessorConditionalExclusion( + Scope *S) { + CodeCompleteOrdinaryName(S, S->getFnParent() + ? SemaCodeCompletion::PCC_RecoveryInFunction + : SemaCodeCompletion::PCC_Namespace); } -void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompletePreprocessorMacroName(bool IsDefinition) { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), IsDefinition ? CodeCompletionContext::CCC_MacroName : CodeCompletionContext::CCC_MacroNameUse); @@ -10020,8 +10097,8 @@ void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) { CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); Results.EnterNewScope(); - for (Preprocessor::macro_iterator M = PP.macro_begin(), - MEnd = PP.macro_end(); + for (Preprocessor::macro_iterator M = SemaRef.PP.macro_begin(), + MEnd = SemaRef.PP.macro_end(); M != MEnd; ++M) { Builder.AddTypedTextChunk( Builder.getAllocator().CopyString(M->first->getName())); @@ -10033,17 +10110,18 @@ void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) { // FIXME: Can we detect when the user just wrote an include guard above? } - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompletePreprocessorExpression() { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompletePreprocessorExpression() { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_PreprocessorExpression); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, CodeCompleter->loadExternal(), true); + AddMacroResults(SemaRef.PP, Results, CodeCompleter->loadExternal(), true); // defined () Results.EnterNewScope(); @@ -10057,14 +10135,13 @@ void Sema::CodeCompletePreprocessorExpression() { Results.AddResult(Builder.TakeString()); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompletePreprocessorMacroArgument(Scope *S, - IdentifierInfo *Macro, - MacroInfo *MacroInfo, - unsigned Argument) { +void SemaCodeCompletion::CodeCompletePreprocessorMacroArgument( + Scope *S, IdentifierInfo *Macro, MacroInfo *MacroInfo, unsigned Argument) { // FIXME: In the future, we could provide "overload" results, much like we // do for function calls. @@ -10075,7 +10152,8 @@ void Sema::CodeCompletePreprocessorMacroArgument(Scope *S, // This handles completion inside an #include filename, e.g. #include NativeRelDir = StringRef(RelDir); llvm::sys::path::native(NativeRelDir); llvm::vfs::FileSystem &FS = - getSourceManager().getFileManager().getVirtualFileSystem(); + SemaRef.getSourceManager().getFileManager().getVirtualFileSystem(); - ResultBuilder Results(*this, CodeCompleter->getAllocator(), + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_IncludedFile); llvm::DenseSet SeenResults; // To deduplicate results. @@ -10197,11 +10275,11 @@ void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) { // Finally with all our helpers, we can scan the include path. // Do this in standard order so deduplication keeps the right file. // (In case we decide to add more details to the results later). - const auto &S = PP.getHeaderSearchInfo(); + const auto &S = SemaRef.PP.getHeaderSearchInfo(); using llvm::make_range; if (!Angled) { // The current directory is on the include path for "quoted" includes. - if (auto CurFile = PP.getCurrentFileLexer()->getFileEntry()) + if (auto CurFile = SemaRef.PP.getCurrentFileLexer()->getFileEntry()) AddFilesFromIncludeDir(CurFile->getDir().getName(), false, DirectoryLookup::LT_NormalDir); for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end())) @@ -10212,18 +10290,19 @@ void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) { for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end())) AddFilesFromDirLookup(D, true); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::CodeCompleteNaturalLanguage() { - HandleCodeCompleteResults(this, CodeCompleter, +void SemaCodeCompletion::CodeCompleteNaturalLanguage() { + HandleCodeCompleteResults(&SemaRef, CodeCompleter, CodeCompletionContext::CCC_NaturalLanguage, nullptr, 0); } -void Sema::CodeCompleteAvailabilityPlatformName() { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), +void SemaCodeCompletion::CodeCompleteAvailabilityPlatformName() { + ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); @@ -10234,28 +10313,33 @@ void Sema::CodeCompleteAvailabilityPlatformName() { Twine(Platform) + "ApplicationExtension"))); } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + HandleCodeCompleteResults(&SemaRef, CodeCompleter, + Results.getCompletionContext(), Results.data(), + Results.size()); } -void Sema::GatherGlobalCodeCompletions( +void SemaCodeCompletion::GatherGlobalCodeCompletions( CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, SmallVectorImpl &Results) { - ResultBuilder Builder(*this, Allocator, CCTUInfo, + ResultBuilder Builder(SemaRef, Allocator, CCTUInfo, CodeCompletionContext::CCC_Recovery); if (!CodeCompleter || CodeCompleter->includeGlobals()) { - CodeCompletionDeclConsumer Consumer(Builder, - Context.getTranslationUnitDecl()); - LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName, - Consumer, - !CodeCompleter || CodeCompleter->loadExternal()); + CodeCompletionDeclConsumer Consumer( + Builder, getASTContext().getTranslationUnitDecl()); + SemaRef.LookupVisibleDecls(getASTContext().getTranslationUnitDecl(), + Sema::LookupAnyName, Consumer, + !CodeCompleter || CodeCompleter->loadExternal()); } if (!CodeCompleter || CodeCompleter->includeMacros()) - AddMacroResults(PP, Builder, + AddMacroResults(SemaRef.PP, Builder, !CodeCompleter || CodeCompleter->loadExternal(), true); Results.clear(); Results.insert(Results.end(), Builder.data(), Builder.data() + Builder.size()); } + +SemaCodeCompletion::SemaCodeCompletion(Sema &S, + CodeCompleteConsumer *CompletionConsumer) + : SemaBase(S), CodeCompleter(CompletionConsumer) {} diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 7bfec4e11f7aab25cea8dbbcea5b850862254299..202dd86c67f62246abcb72acc48f44f933e2abbb 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -1162,6 +1162,13 @@ static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, break; } return; + } else if (auto *TTE = dyn_cast(SubstExpr); + TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) { + assert(TTE->getNumArgs() == 2); + S.Diag(SubstExpr->getSourceRange().getBegin(), + diag::note_is_deducible_constraint_evaluated_to_false) + << TTE->getArg(0)->getType() << TTE->getArg(1)->getType(); + return; } S.Diag(SubstExpr->getSourceRange().getBegin(), diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 0dbdf923df95a14e9adc84a03d219bd87660eb39..6764a979168d6e91aba8e951240f9ce5ca508dfc 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2465,9 +2465,9 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, /// entity if their types are the same. /// FIXME: This is notionally doing the same thing as ASTReaderDecl's /// isSameEntity. -static void filterNonConflictingPreviousTypedefDecls(Sema &S, - TypedefNameDecl *Decl, - LookupResult &Previous) { +static void +filterNonConflictingPreviousTypedefDecls(Sema &S, const TypedefNameDecl *Decl, + LookupResult &Previous) { // This is only interesting when modules are enabled. if (!S.getLangOpts().Modules && !S.getLangOpts().ModulesLocalVisibility) return; @@ -2504,9 +2504,9 @@ static void filterNonConflictingPreviousTypedefDecls(Sema &S, Filter.done(); } -bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) { +bool Sema::isIncompatibleTypedef(const TypeDecl *Old, TypedefNameDecl *New) { QualType OldType; - if (TypedefNameDecl *OldTypedef = dyn_cast(Old)) + if (const TypedefNameDecl *OldTypedef = dyn_cast(Old)) OldType = OldTypedef->getUnderlyingType(); else OldType = Context.getTypeDeclType(Old); @@ -2879,7 +2879,7 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, D, *AA, AA->getPlatform(), AA->isImplicit(), AA->getIntroduced(), AA->getDeprecated(), AA->getObsoleted(), AA->getUnavailable(), AA->getMessage(), AA->getStrict(), AA->getReplacement(), AMK, - AA->getPriority()); + AA->getPriority(), AA->getEnvironment()); else if (const auto *VA = dyn_cast(Attr)) NewAttr = S.mergeVisibilityAttr(D, *VA, VA->getVisibility()); else if (const auto *VA = dyn_cast(Attr)) @@ -7573,6 +7573,11 @@ NamedDecl *Sema::ActOnVariableDeclarator( tryToFixVariablyModifiedVarType(TInfo, R, D.getIdentifierLoc(), /*DiagID=*/0); + if (const AutoType *AutoT = R->getAs()) + CheckConstrainedAuto( + AutoT, + TInfo->getTypeLoc().getContainedAutoTypeLoc().getConceptNameLoc()); + bool IsMemberSpecialization = false; bool IsVariableTemplateSpecialization = false; bool IsPartialSpecialization = false; @@ -8900,11 +8905,20 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { const FunctionDecl *FD = cast(CurContext); llvm::StringMap CallerFeatureMap; Context.getFunctionFeatureMap(CallerFeatureMap, FD); - if (!Builtin::evaluateRequiredTargetFeatures( - "sve", CallerFeatureMap)) { - Diag(NewVD->getLocation(), diag::err_sve_vector_in_non_sve_target) << T; - NewVD->setInvalidDecl(); - return; + + if (!Builtin::evaluateRequiredTargetFeatures("sve", CallerFeatureMap)) { + if (!Builtin::evaluateRequiredTargetFeatures("sme", CallerFeatureMap)) { + Diag(NewVD->getLocation(), diag::err_sve_vector_in_non_sve_target) << T; + NewVD->setInvalidDecl(); + return; + } else if (!IsArmStreamingFunction(FD, + /*IncludeLocallyStreaming=*/true)) { + Diag(NewVD->getLocation(), + diag::err_sve_vector_in_non_streaming_function) + << T; + NewVD->setInvalidDecl(); + return; + } } } @@ -9203,19 +9217,20 @@ static NamedDecl *DiagnoseInvalidRedeclaration( << Idx << FDParam->getType() << NewFD->getParamDecl(Idx - 1)->getType(); } else if (FDisConst != NewFDisConst) { - SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) - << NewFDisConst << FD->getSourceRange().getEnd() - << (NewFDisConst - ? FixItHint::CreateRemoval(ExtraArgs.D.getFunctionTypeInfo() - .getConstQualifierLoc()) - : FixItHint::CreateInsertion(ExtraArgs.D.getFunctionTypeInfo() - .getRParenLoc() - .getLocWithOffset(1), - " const")); - } else + auto DB = SemaRef.Diag(FD->getLocation(), + diag::note_member_def_close_const_match) + << NewFDisConst << FD->getSourceRange().getEnd(); + if (const auto &FTI = ExtraArgs.D.getFunctionTypeInfo(); !NewFDisConst) + DB << FixItHint::CreateInsertion(FTI.getRParenLoc().getLocWithOffset(1), + " const"); + else if (FTI.hasMethodTypeQualifiers() && + FTI.getConstQualifierLoc().isValid()) + DB << FixItHint::CreateRemoval(FTI.getConstQualifierLoc()); + } else { SemaRef.Diag(FD->getLocation(), IsMember ? diag::note_member_def_close_match : diag::note_local_decl_close_match); + } } return nullptr; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 777171f4f15f5ebc65fd298e1dac41f49fafc615..ca5938083917f72bedcfb57252bdcc3cfb60d151 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -26,6 +26,7 @@ #include "clang/Basic/Cuda.h" #include "clang/Basic/DarwinSDKInfo.h" #include "clang/Basic/HLSLRuntime.h" +#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" @@ -52,6 +53,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/Triple.h" #include using namespace clang; @@ -640,7 +642,7 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D, if (const auto *StrLit = dyn_cast(ArgExp)) { if (StrLit->getLength() == 0 || - (StrLit->isOrdinary() && StrLit->getString() == StringRef("*"))) { + (StrLit->isOrdinary() && StrLit->getString() == "*")) { // Pass empty strings to the analyzer without warnings. // Treat "*" as the universal lock. Args.push_back(ArgExp); @@ -2495,7 +2497,7 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr( bool Implicit, VersionTuple Introduced, VersionTuple Deprecated, VersionTuple Obsoleted, bool IsUnavailable, StringRef Message, bool IsStrict, StringRef Replacement, AvailabilityMergeKind AMK, - int Priority) { + int Priority, IdentifierInfo *Environment) { VersionTuple MergedIntroduced = Introduced; VersionTuple MergedDeprecated = Deprecated; VersionTuple MergedObsoleted = Obsoleted; @@ -2529,6 +2531,12 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr( continue; } + IdentifierInfo *OldEnvironment = OldAA->getEnvironment(); + if (OldEnvironment != Environment) { + ++i; + continue; + } + // If there is an existing availability attribute for this platform that // has a lower priority use the existing one and discard the new // attribute. @@ -2647,7 +2655,7 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr( !OverrideOrImpl) { auto *Avail = ::new (Context) AvailabilityAttr( Context, CI, Platform, Introduced, Deprecated, Obsoleted, IsUnavailable, - Message, IsStrict, Replacement, Priority); + Message, IsStrict, Replacement, Priority, Environment); Avail->setImplicit(Implicit); return Avail; } @@ -2706,13 +2714,34 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } } + if (S.getLangOpts().HLSL && IsStrict) + S.Diag(AL.getStrictLoc(), diag::err_availability_unexpected_parameter) + << "strict" << /* HLSL */ 0; + int PriorityModifier = AL.isPragmaClangAttribute() ? Sema::AP_PragmaClangAttribute : Sema::AP_Explicit; + + const IdentifierLoc *EnvironmentLoc = AL.getEnvironment(); + IdentifierInfo *IIEnvironment = nullptr; + if (EnvironmentLoc) { + if (S.getLangOpts().HLSL) { + IIEnvironment = EnvironmentLoc->Ident; + if (AvailabilityAttr::getEnvironmentType( + EnvironmentLoc->Ident->getName()) == + llvm::Triple::EnvironmentType::UnknownEnvironment) + S.Diag(EnvironmentLoc->Loc, diag::warn_availability_unknown_environment) + << EnvironmentLoc->Ident; + } else { + S.Diag(EnvironmentLoc->Loc, diag::err_availability_unexpected_parameter) + << "environment" << /* C/C++ */ 1; + } + } + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( ND, AL, II, false /*Implicit*/, Introduced.Version, Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, IsStrict, Replacement, - Sema::AMK_None, PriorityModifier); + Sema::AMK_None, PriorityModifier, IIEnvironment); if (NewAttr) D->addAttr(NewAttr); @@ -2768,8 +2797,8 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated, NewObsoleted, IsUnavailable, Str, IsStrict, Replacement, - Sema::AMK_None, - PriorityModifier + Sema::AP_InferredFromOtherPlatform); + Sema::AMK_None, PriorityModifier + Sema::AP_InferredFromOtherPlatform, + IIEnvironment); if (NewAttr) D->addAttr(NewAttr); } @@ -2810,8 +2839,8 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated, NewObsoleted, IsUnavailable, Str, IsStrict, Replacement, - Sema::AMK_None, - PriorityModifier + Sema::AP_InferredFromOtherPlatform); + Sema::AMK_None, PriorityModifier + Sema::AP_InferredFromOtherPlatform, + IIEnvironment); if (NewAttr) D->addAttr(NewAttr); } @@ -2844,7 +2873,7 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { MinMacCatalystVersion(Deprecated.Version), MinMacCatalystVersion(Obsoleted.Version), IsUnavailable, Str, IsStrict, Replacement, Sema::AMK_None, - PriorityModifier + Sema::AP_InferredFromOtherPlatform); + PriorityModifier + Sema::AP_InferredFromOtherPlatform, IIEnvironment); if (NewAttr) D->addAttr(NewAttr); } else if (II->getName() == "macos" && GetSDKInfo() && @@ -2887,7 +2916,8 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { VersionOrEmptyVersion(NewObsoleted), /*IsUnavailable=*/false, Str, IsStrict, Replacement, Sema::AMK_None, PriorityModifier + Sema::AP_InferredFromOtherPlatform + - Sema::AP_InferredFromOtherPlatform); + Sema::AP_InferredFromOtherPlatform, + IIEnvironment); if (NewAttr) D->addAttr(NewAttr); } @@ -3645,7 +3675,7 @@ bool Sema::checkTargetClonesAttrString( llvm::sort(CurFeatures); SmallString<64> Res; for (auto &CurFeat : CurFeatures) { - if (!Res.equals("")) + if (!Res.empty()) Res.append("+"); Res.append(CurFeat); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ec84798e4ce6093ca0fb91c03da3e15b25ae6dd7..f2d0a93d9a1e7ad90a42589cc1f335158f0e4327 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -672,12 +672,12 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // We don't want to throw lvalue-to-rvalue casts on top of // expressions of certain types in C++. - if (getLangOpts().CPlusPlus && - (E->getType() == Context.OverloadTy || - // FIXME: This is a hack! We want the lvalue-to-rvalue conversion applied - // to pointer types even if the pointee type is dependent. - (T->isDependentType() && !T->isPointerType()) || T->isRecordType())) - return E; + if (getLangOpts().CPlusPlus) { + if (T == Context.OverloadTy || T->isRecordType() || + (T->isDependentType() && !T->isAnyPointerType() && + !T->isMemberPointerType())) + return E; + } // The C standard is actually really unclear on this point, and // DR106 tells us what the result should be but not why. It's @@ -3699,7 +3699,10 @@ static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal, using llvm::APFloat; APFloat Val(Format); - APFloat::opStatus result = Literal.GetFloatValue(Val); + llvm::RoundingMode RM = S.CurFPFeatures.getRoundingMode(); + if (RM == llvm::RoundingMode::Dynamic) + RM = llvm::RoundingMode::NearestTiesToEven; + APFloat::opStatus result = Literal.GetFloatValue(Val, RM); // Overflow is always an error, but underflow is only an error if // we underflowed to zero (APFloat reports denormals as underflow). @@ -3715,9 +3718,7 @@ static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal, APFloat::getSmallest(Format).toString(buffer); } - S.Diag(Loc, diagnostic) - << Ty - << StringRef(buffer.data(), buffer.size()); + S.Diag(Loc, diagnostic) << Ty << buffer.str(); } bool isExact = (result == APFloat::opOK); @@ -5618,9 +5619,10 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, Res = Immediate.TransformInitializer(Param->getInit(), /*NotCopy=*/false); }); - if (Res.isUsable()) - Res = ConvertParamDefaultArgument(Param, Res.get(), - Res.get()->getBeginLoc()); + if (Res.isInvalid()) + return ExprError(); + Res = ConvertParamDefaultArgument(Param, Res.get(), + Res.get()->getBeginLoc()); if (Res.isInvalid()) return ExprError(); Init = Res.get(); @@ -5656,7 +5658,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Expr *Init = nullptr; bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer(); - bool InLifetimeExtendingContext = isInLifetimeExtendingContext(); + EnterExpressionEvaluationContext EvalContext( *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field); @@ -5691,35 +5693,19 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { ImmediateCallVisitor V(getASTContext()); if (!NestedDefaultChecking) V.TraverseDecl(Field); - - // CWG1815 - // Support lifetime extension of temporary created by aggregate - // initialization using a default member initializer. We should always rebuild - // the initializer if it contains any temporaries (if the initializer - // expression is an ExprWithCleanups). Then make sure the normal lifetime - // extension code recurses into the default initializer and does lifetime - // extension when warranted. - bool ContainsAnyTemporaries = - isa_and_present(Field->getInClassInitializer()); - if (V.HasImmediateCalls || InLifetimeExtendingContext || - ContainsAnyTemporaries) { + if (V.HasImmediateCalls) { ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field, CurContext}; ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = NestedDefaultChecking; - // Pass down lifetime extending flag, and collect temporaries in - // CreateMaterializeTemporaryExpr when we rewrite the call argument. - keepInLifetimeExtendingContext(); + EnsureImmediateInvocationInDefaultArgs Immediate(*this); ExprResult Res; - - // Rebuild CXXDefaultInitExpr might cause diagnostics. - SFINAETrap Trap(*this); runWithSufficientStackSpace(Loc, [&] { Res = Immediate.TransformInitializer(Field->getInClassInitializer(), /*CXXDirectInit=*/false); }); - if (Res.isUsable()) + if (!Res.isInvalid()) Res = ConvertMemberDefaultInitExpression(Field, Res.get(), Loc); if (Res.isInvalid()) { Field->setInvalidDecl(); @@ -7130,12 +7116,19 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, // init a VLA in C++ in all cases (such as with non-trivial constructors). // FIXME: should we allow this construct in C++ when it makes sense to do // so? - std::optional NumInits; - if (const auto *ILE = dyn_cast(LiteralExpr)) - NumInits = ILE->getNumInits(); - if ((LangOpts.CPlusPlus || NumInits.value_or(0)) && - !tryToFixVariablyModifiedVarType(TInfo, literalType, LParenLoc, - diag::err_variable_object_no_init)) + // + // But: C99-C23 6.5.2.5 Compound literals constraint 1: The type name + // shall specify an object type or an array of unknown size, but not a + // variable length array type. This seems odd, as it allows 'int a[size] = + // {}', but forbids 'int *a = (int[size]){}'. As this is what the standard + // says, this is what's implemented here for C (except for the extension + // that permits constant foldable size arrays) + + auto diagID = LangOpts.CPlusPlus + ? diag::err_variable_object_no_init + : diag::err_compound_literal_with_vla_type; + if (!tryToFixVariablyModifiedVarType(TInfo, literalType, LParenLoc, + diagID)) return ExprError(); } } else if (!literalType->isDependentType() && @@ -10827,7 +10820,7 @@ static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc, if (const AtomicType *ResAtomicType = ResType->getAs()) ResType = ResAtomicType->getValueType(); - assert(ResType->isAnyPointerType() && !ResType->isDependentType()); + assert(ResType->isAnyPointerType()); QualType PointeeTy = ResType->getPointeeType(); return S.RequireCompleteSizedType( Loc, PointeeTy, @@ -13957,9 +13950,6 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, ExprObjectKind &OK, SourceLocation OpLoc, bool IsInc, bool IsPrefix) { - if (Op->isTypeDependent()) - return S.Context.DependentTy; - QualType ResType = Op->getType(); // Atomic types can be used for increment / decrement where the non-atomic // versions can, so ignore the _Atomic() specifier for the purpose of @@ -14410,9 +14400,6 @@ static void RecordModifiableNonNullParam(Sema &S, const Expr *Exp) { static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK, SourceLocation OpLoc, bool IsAfterAmp = false) { - if (Op->isTypeDependent()) - return S.Context.DependentTy; - ExprResult ConvResult = S.UsualUnaryConversions(Op); if (ConvResult.isInvalid()) return QualType(); @@ -14878,6 +14865,11 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, case BO_GT: ConvertHalfVec = true; ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc); + + if (const auto *BI = dyn_cast(LHSExpr); + BI && BI->isComparisonOp()) + Diag(OpLoc, diag::warn_consecutive_comparison); + break; case BO_EQ: case BO_NE: @@ -15368,14 +15360,10 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, } if (getLangOpts().CPlusPlus) { - // If either expression is type-dependent, always build an - // overloaded op. - if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent()) - return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); - - // Otherwise, build an overloaded op if either expression has an - // overloadable type. - if (LHSExpr->getType()->isOverloadableType() || + // Otherwise, build an overloaded op if either expression is type-dependent + // or has an overloadable type. + if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent() || + LHSExpr->getType()->isOverloadableType() || RHSExpr->getType()->isOverloadableType()) return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); } @@ -15466,190 +15454,191 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, return ExprError(Diag(OpLoc, diag::err_hlsl_operator_unsupported) << 1); } - switch (Opc) { - case UO_PreInc: - case UO_PreDec: - case UO_PostInc: - case UO_PostDec: - resultType = - CheckIncrementDecrementOperand(*this, Input.get(), VK, OK, OpLoc, - Opc == UO_PreInc || Opc == UO_PostInc, - Opc == UO_PreInc || Opc == UO_PreDec); - CanOverflow = isOverflowingIntegerType(Context, resultType); - break; - case UO_AddrOf: - resultType = CheckAddressOfOperand(Input, OpLoc); - CheckAddressOfNoDeref(InputExpr); - RecordModifiableNonNullParam(*this, InputExpr); - break; - case UO_Deref: { - Input = DefaultFunctionArrayLvalueConversion(Input.get()); - if (Input.isInvalid()) - return ExprError(); - resultType = - CheckIndirectionOperand(*this, Input.get(), VK, OpLoc, IsAfterAmp); - break; - } - case UO_Plus: - case UO_Minus: - CanOverflow = Opc == UO_Minus && - isOverflowingIntegerType(Context, Input.get()->getType()); - Input = UsualUnaryConversions(Input.get()); - if (Input.isInvalid()) - return ExprError(); - // Unary plus and minus require promoting an operand of half vector to a - // float vector and truncating the result back to a half vector. For now, we - // do this only when HalfArgsAndReturns is set (that is, when the target is - // arm or arm64). - ConvertHalfVec = needsConversionOfHalfVec(true, Context, Input.get()); - - // If the operand is a half vector, promote it to a float vector. - if (ConvertHalfVec) - Input = convertVector(Input.get(), Context.FloatTy, *this); - resultType = Input.get()->getType(); - if (resultType->isDependentType()) - break; - if (resultType->isArithmeticType()) // C99 6.5.3.3p1 - break; - else if (resultType->isVectorType() && - // The z vector extensions don't allow + or - with bool vectors. - (!Context.getLangOpts().ZVector || - resultType->castAs()->getVectorKind() != - VectorKind::AltiVecBool)) - break; - else if (resultType->isSveVLSBuiltinType()) // SVE vectors allow + and - - break; - else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6 - Opc == UO_Plus && resultType->isPointerType()) + if (InputExpr->isTypeDependent() && + InputExpr->getType()->isSpecificBuiltinType(BuiltinType::Dependent)) { + resultType = Context.DependentTy; + } else { + switch (Opc) { + case UO_PreInc: + case UO_PreDec: + case UO_PostInc: + case UO_PostDec: + resultType = + CheckIncrementDecrementOperand(*this, Input.get(), VK, OK, OpLoc, + Opc == UO_PreInc || Opc == UO_PostInc, + Opc == UO_PreInc || Opc == UO_PreDec); + CanOverflow = isOverflowingIntegerType(Context, resultType); break; - - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - - case UO_Not: // bitwise complement - Input = UsualUnaryConversions(Input.get()); - if (Input.isInvalid()) - return ExprError(); - resultType = Input.get()->getType(); - if (resultType->isDependentType()) + case UO_AddrOf: + resultType = CheckAddressOfOperand(Input, OpLoc); + CheckAddressOfNoDeref(InputExpr); + RecordModifiableNonNullParam(*this, InputExpr); break; - // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. - if (resultType->isComplexType() || resultType->isComplexIntegerType()) - // C99 does not support '~' for complex conjugation. - Diag(OpLoc, diag::ext_integer_complement_complex) - << resultType << Input.get()->getSourceRange(); - else if (resultType->hasIntegerRepresentation()) + case UO_Deref: { + Input = DefaultFunctionArrayLvalueConversion(Input.get()); + if (Input.isInvalid()) + return ExprError(); + resultType = + CheckIndirectionOperand(*this, Input.get(), VK, OpLoc, IsAfterAmp); break; - else if (resultType->isExtVectorType() && Context.getLangOpts().OpenCL) { - // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate - // on vector float types. - QualType T = resultType->castAs()->getElementType(); - if (!T->isIntegerType()) - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } else { - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } - break; - - case UO_LNot: // logical negation - // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). - Input = DefaultFunctionArrayLvalueConversion(Input.get()); - if (Input.isInvalid()) - return ExprError(); - resultType = Input.get()->getType(); - - // Though we still have to promote half FP to float... - if (resultType->isHalfType() && !Context.getLangOpts().NativeHalfType) { - Input = ImpCastExprToType(Input.get(), Context.FloatTy, CK_FloatingCast) - .get(); - resultType = Context.FloatTy; } + case UO_Plus: + case UO_Minus: + CanOverflow = Opc == UO_Minus && + isOverflowingIntegerType(Context, Input.get()->getType()); + Input = UsualUnaryConversions(Input.get()); + if (Input.isInvalid()) + return ExprError(); + // Unary plus and minus require promoting an operand of half vector to a + // float vector and truncating the result back to a half vector. For now, + // we do this only when HalfArgsAndReturns is set (that is, when the + // target is arm or arm64). + ConvertHalfVec = needsConversionOfHalfVec(true, Context, Input.get()); + + // If the operand is a half vector, promote it to a float vector. + if (ConvertHalfVec) + Input = convertVector(Input.get(), Context.FloatTy, *this); + resultType = Input.get()->getType(); + if (resultType->isArithmeticType()) // C99 6.5.3.3p1 + break; + else if (resultType->isVectorType() && + // The z vector extensions don't allow + or - with bool vectors. + (!Context.getLangOpts().ZVector || + resultType->castAs()->getVectorKind() != + VectorKind::AltiVecBool)) + break; + else if (resultType->isSveVLSBuiltinType()) // SVE vectors allow + and - + break; + else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6 + Opc == UO_Plus && resultType->isPointerType()) + break; - // WebAsembly tables can't be used in unary expressions. - if (resultType->isPointerType() && - resultType->getPointeeType().isWebAssemblyReferenceType()) { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); - } - if (resultType->isDependentType()) - break; - if (resultType->isScalarType() && !isScopedEnumerationType(resultType)) { - // C99 6.5.3.3p1: ok, fallthrough; - if (Context.getLangOpts().CPlusPlus) { - // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9: - // operand contextually converted to bool. - Input = ImpCastExprToType(Input.get(), Context.BoolTy, - ScalarTypeToBooleanCastKind(resultType)); - } else if (Context.getLangOpts().OpenCL && - Context.getLangOpts().OpenCLVersion < 120) { - // OpenCL v1.1 6.3.h: The logical operator not (!) does not - // operate on scalar float types. - if (!resultType->isIntegerType() && !resultType->isPointerType()) - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } - } else if (resultType->isExtVectorType()) { - if (Context.getLangOpts().OpenCL && - Context.getLangOpts().getOpenCLCompatibleVersion() < 120) { - // OpenCL v1.1 6.3.h: The logical operator not (!) does not - // operate on vector float types. + case UO_Not: // bitwise complement + Input = UsualUnaryConversions(Input.get()); + if (Input.isInvalid()) + return ExprError(); + resultType = Input.get()->getType(); + // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. + if (resultType->isComplexType() || resultType->isComplexIntegerType()) + // C99 does not support '~' for complex conjugation. + Diag(OpLoc, diag::ext_integer_complement_complex) + << resultType << Input.get()->getSourceRange(); + else if (resultType->hasIntegerRepresentation()) + break; + else if (resultType->isExtVectorType() && Context.getLangOpts().OpenCL) { + // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate + // on vector float types. QualType T = resultType->castAs()->getElementType(); if (!T->isIntegerType()) return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); + } else { + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); } - // Vector logical not returns the signed variant of the operand type. - resultType = GetSignedVectorType(resultType); break; - } else if (Context.getLangOpts().CPlusPlus && resultType->isVectorType()) { - const VectorType *VTy = resultType->castAs(); - if (VTy->getVectorKind() != VectorKind::Generic) + + case UO_LNot: // logical negation + // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). + Input = DefaultFunctionArrayLvalueConversion(Input.get()); + if (Input.isInvalid()) + return ExprError(); + resultType = Input.get()->getType(); + + // Though we still have to promote half FP to float... + if (resultType->isHalfType() && !Context.getLangOpts().NativeHalfType) { + Input = ImpCastExprToType(Input.get(), Context.FloatTy, CK_FloatingCast) + .get(); + resultType = Context.FloatTy; + } + + // WebAsembly tables can't be used in unary expressions. + if (resultType->isPointerType() && + resultType->getPointeeType().isWebAssemblyReferenceType()) { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); + } - // Vector logical not returns the signed variant of the operand type. - resultType = GetSignedVectorType(resultType); - break; - } else { - return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); - } + if (resultType->isScalarType() && !isScopedEnumerationType(resultType)) { + // C99 6.5.3.3p1: ok, fallthrough; + if (Context.getLangOpts().CPlusPlus) { + // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9: + // operand contextually converted to bool. + Input = ImpCastExprToType(Input.get(), Context.BoolTy, + ScalarTypeToBooleanCastKind(resultType)); + } else if (Context.getLangOpts().OpenCL && + Context.getLangOpts().OpenCLVersion < 120) { + // OpenCL v1.1 6.3.h: The logical operator not (!) does not + // operate on scalar float types. + if (!resultType->isIntegerType() && !resultType->isPointerType()) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + } else if (resultType->isExtVectorType()) { + if (Context.getLangOpts().OpenCL && + Context.getLangOpts().getOpenCLCompatibleVersion() < 120) { + // OpenCL v1.1 6.3.h: The logical operator not (!) does not + // operate on vector float types. + QualType T = resultType->castAs()->getElementType(); + if (!T->isIntegerType()) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + // Vector logical not returns the signed variant of the operand type. + resultType = GetSignedVectorType(resultType); + break; + } else if (Context.getLangOpts().CPlusPlus && + resultType->isVectorType()) { + const VectorType *VTy = resultType->castAs(); + if (VTy->getVectorKind() != VectorKind::Generic) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); - // LNot always has type int. C99 6.5.3.3p5. - // In C++, it's bool. C++ 5.3.1p8 - resultType = Context.getLogicalOperationType(); - break; - case UO_Real: - case UO_Imag: - resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real); - // _Real maps ordinary l-values into ordinary l-values. _Imag maps ordinary - // complex l-values to ordinary l-values and all other values to r-values. - if (Input.isInvalid()) - return ExprError(); - if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) { - if (Input.get()->isGLValue() && - Input.get()->getObjectKind() == OK_Ordinary) - VK = Input.get()->getValueKind(); - } else if (!getLangOpts().CPlusPlus) { - // In C, a volatile scalar is read by __imag. In C++, it is not. - Input = DefaultLvalueConversion(Input.get()); + // Vector logical not returns the signed variant of the operand type. + resultType = GetSignedVectorType(resultType); + break; + } else { + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + + // LNot always has type int. C99 6.5.3.3p5. + // In C++, it's bool. C++ 5.3.1p8 + resultType = Context.getLogicalOperationType(); + break; + case UO_Real: + case UO_Imag: + resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real); + // _Real maps ordinary l-values into ordinary l-values. _Imag maps + // ordinary complex l-values to ordinary l-values and all other values to + // r-values. + if (Input.isInvalid()) + return ExprError(); + if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) { + if (Input.get()->isGLValue() && + Input.get()->getObjectKind() == OK_Ordinary) + VK = Input.get()->getValueKind(); + } else if (!getLangOpts().CPlusPlus) { + // In C, a volatile scalar is read by __imag. In C++, it is not. + Input = DefaultLvalueConversion(Input.get()); + } + break; + case UO_Extension: + resultType = Input.get()->getType(); + VK = Input.get()->getValueKind(); + OK = Input.get()->getObjectKind(); + break; + case UO_Coawait: + // It's unnecessary to represent the pass-through operator co_await in the + // AST; just return the input expression instead. + assert(!Input.get()->getType()->isDependentType() && + "the co_await expression must be non-dependant before " + "building operator co_await"); + return Input; } - break; - case UO_Extension: - resultType = Input.get()->getType(); - VK = Input.get()->getValueKind(); - OK = Input.get()->getObjectKind(); - break; - case UO_Coawait: - // It's unnecessary to represent the pass-through operator co_await in the - // AST; just return the input expression instead. - assert(!Input.get()->getType()->isDependentType() && - "the co_await expression must be non-dependant before " - "building operator co_await"); - return Input; } if (resultType.isNull() || Input.isInvalid()) return ExprError(); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 34e12078a8c929a4cca2266d26b69c4a646b5006..f543e006060d6214dfc76f7da28df55511f1778f 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5217,10 +5217,18 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, case UTT_IsFloatingPoint: return T->isFloatingType(); case UTT_IsArray: + // Zero-sized arrays aren't considered arrays in partial specializations, + // so __is_array shouldn't consider them arrays either. + if (const auto *CAT = C.getAsConstantArrayType(T)) + return CAT->getSize() != 0; return T->isArrayType(); case UTT_IsBoundedArray: if (DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___is_bounded_array)) return false; + // Zero-sized arrays aren't considered arrays in partial specializations, + // so __is_bounded_array shouldn't consider them arrays either. + if (const auto *CAT = C.getAsConstantArrayType(T)) + return CAT->getSize() != 0; return T->isArrayType() && !T->isIncompleteArrayType(); case UTT_IsUnboundedArray: if (DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___is_unbounded_array)) @@ -6143,7 +6151,15 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs); } - default: llvm_unreachable("not a BTT"); + case BTT_IsDeducible: { + const auto *TSTToBeDeduced = cast(LhsT); + sema::TemplateDeductionInfo Info(KeyLoc); + return Self.DeduceTemplateArgumentsFromType( + TSTToBeDeduced->getTemplateName().getAsTemplateDecl(), RhsT, + Info) == TemplateDeductionResult::Success; + } + default: + llvm_unreachable("not a BTT"); } llvm_unreachable("Unknown type trait or not implemented"); } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 708286e192f9c19497ee8048bece77f332d5c2bd..353e911c5cc337f3a0215d8d52f8db233b44e30d 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -876,7 +876,7 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, InitializedEntity ElementEntity = Entity; unsigned NumInits = ILE->getNumInits(); - unsigned NumElements = NumInits; + uint64_t NumElements = NumInits; if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) { ElementType = AType->getElementType(); if (const auto *CAType = dyn_cast(AType)) @@ -896,7 +896,7 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, ElementType = ILE->getType(); bool SkipEmptyInitChecks = false; - for (unsigned Init = 0; Init != NumElements; ++Init) { + for (uint64_t Init = 0; Init != NumElements; ++Init) { if (hadError) return; @@ -8066,6 +8066,11 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, enum PathLifetimeKind { /// Lifetime-extend along this path. Extend, + /// We should lifetime-extend, but we don't because (due to technical + /// limitations) we can't. This happens for default member initializers, + /// which we don't clone for every use, so we don't have a unique + /// MaterializeTemporaryExpr to update. + ShouldExtend, /// Do not lifetime extend along this path. NoExtend }; @@ -8077,7 +8082,7 @@ shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { PathLifetimeKind Kind = PathLifetimeKind::Extend; for (auto Elem : Path) { if (Elem.Kind == IndirectLocalPathEntry::DefaultInit) - Kind = PathLifetimeKind::Extend; + Kind = PathLifetimeKind::ShouldExtend; else if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit) return PathLifetimeKind::NoExtend; } @@ -8197,6 +8202,18 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, ExtendingEntity->allocateManglingNumber()); // Also visit the temporaries lifetime-extended by this initializer. return true; + + case PathLifetimeKind::ShouldExtend: + // We're supposed to lifetime-extend the temporary along this path (per + // the resolution of DR1815), but we don't support that yet. + // + // FIXME: Properly handle this situation. Perhaps the easiest approach + // would be to clone the initializer expression on each use that would + // lifetime extend its temporaries. + Diag(DiagLoc, diag::warn_unsupported_lifetime_extension) + << RK << DiagRange; + break; + case PathLifetimeKind::NoExtend: // If the path goes through the initialization of a variable or field, // it can't possibly reach a temporary created in this full-expression. diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 7d00cf6fb5b6a1797c35fd73f40a5a9c0aad56cb..6110e5229b076cdf541807980bc789e0486b6872 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -3757,7 +3757,8 @@ public: void VisitDeclRefExpr(DeclRefExpr *E) { if (TryCaptureCXXThisMembers || E->isTypeDependent() || E->isValueDependent() || E->containsUnexpandedParameterPack() || - E->isInstantiationDependent()) + E->isInstantiationDependent() || + E->isNonOdrUse() == clang::NOUR_Unevaluated) return; if (auto *VD = dyn_cast(E->getDecl())) { // Check the datasharing rules for the expressions in the clauses. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index c7aac068e264b7d442bf2b761b6f3289793892d9..8a7af678b33d39ede3149fbe8e5044e5001dde9d 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2782,17 +2782,24 @@ NamedDecl *transformTemplateParameter(Sema &SemaRef, DeclContext *DC, llvm_unreachable("Unhandled template parameter types"); } -// Transform the require-clause of F if any. +// Build the associated constraints for the alias deduction guides. +// C++ [over.match.class.deduct]p3.3: +// The associated constraints ([temp.constr.decl]) are the conjunction of the +// associated constraints of g and a constraint that is satisfied if and only +// if the arguments of A are deducible (see below) from the return type. +// // The return result is expected to be the require-clause for the synthesized // alias deduction guide. -Expr *transformRequireClause(Sema &SemaRef, FunctionTemplateDecl *F, - TypeAliasTemplateDecl *AliasTemplate, - ArrayRef DeduceResults) { +Expr * +buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F, + TypeAliasTemplateDecl *AliasTemplate, + ArrayRef DeduceResults, + Expr *IsDeducible) { Expr *RC = F->getTemplateParameters()->getRequiresClause(); if (!RC) - return nullptr; + return IsDeducible; - auto &Context = SemaRef.Context; + ASTContext &Context = SemaRef.Context; LocalInstantiationScope Scope(SemaRef); // In the clang AST, constraint nodes are deliberately not instantiated unless @@ -2903,7 +2910,68 @@ Expr *transformRequireClause(Sema &SemaRef, FunctionTemplateDecl *F, ExprResult E = SemaRef.SubstExpr(RC, ArgsForBuildingRC); if (E.isInvalid()) return nullptr; - return E.getAs(); + + auto Conjunction = + SemaRef.BuildBinOp(SemaRef.getCurScope(), SourceLocation{}, + BinaryOperatorKind::BO_LAnd, E.get(), IsDeducible); + if (Conjunction.isInvalid()) + return nullptr; + return Conjunction.getAs(); +} +// Build the is_deducible constraint for the alias deduction guides. +// [over.match.class.deduct]p3.3: +// ... and a constraint that is satisfied if and only if the arguments +// of A are deducible (see below) from the return type. +Expr *buildIsDeducibleConstraint(Sema &SemaRef, + TypeAliasTemplateDecl *AliasTemplate, + QualType ReturnType, + SmallVector TemplateParams) { + ASTContext &Context = SemaRef.Context; + // Constraint AST nodes must use uninstantiated depth. + if (auto *PrimaryTemplate = + AliasTemplate->getInstantiatedFromMemberTemplate()) { + LocalInstantiationScope Scope(SemaRef); + + // Adjust the depth for TemplateParams. + unsigned AdjustDepth = PrimaryTemplate->getTemplateDepth(); + SmallVector TransformedTemplateArgs; + for (auto *TP : TemplateParams) { + // Rebuild any internal references to earlier parameters and reindex + // as we go. + MultiLevelTemplateArgumentList Args; + Args.setKind(TemplateSubstitutionKind::Rewrite); + Args.addOuterTemplateArguments(TransformedTemplateArgs); + NamedDecl *NewParam = transformTemplateParameter( + SemaRef, AliasTemplate->getDeclContext(), TP, Args, + /*NewIndex=*/TransformedTemplateArgs.size(), + getTemplateParameterDepth(TP) + AdjustDepth); + + auto NewTemplateArgument = Context.getCanonicalTemplateArgument( + Context.getInjectedTemplateArg(NewParam)); + TransformedTemplateArgs.push_back(NewTemplateArgument); + } + // Transformed the ReturnType to restore the uninstantiated depth. + MultiLevelTemplateArgumentList Args; + Args.setKind(TemplateSubstitutionKind::Rewrite); + Args.addOuterTemplateArguments(TransformedTemplateArgs); + ReturnType = SemaRef.SubstType( + ReturnType, Args, AliasTemplate->getLocation(), + Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate)); + }; + + SmallVector IsDeducibleTypeTraitArgs = { + Context.getTrivialTypeSourceInfo( + Context.getDeducedTemplateSpecializationType( + TemplateName(AliasTemplate), /*DeducedType=*/QualType(), + /*IsDependent=*/true)), // template specialization type whose + // arguments will be deduced. + Context.getTrivialTypeSourceInfo( + ReturnType), // type from which template arguments are deduced. + }; + return TypeTraitExpr::Create( + Context, Context.getLogicalOperationType(), AliasTemplate->getLocation(), + TypeTrait::BTT_IsDeducible, IsDeducibleTypeTraitArgs, + AliasTemplate->getLocation(), /*Value*/ false); } std::pair> @@ -3112,8 +3180,10 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, Sema::CodeSynthesisContext::BuildingDeductionGuides)) { auto *GG = cast(FPrime); - Expr *RequiresClause = - transformRequireClause(SemaRef, F, AliasTemplate, DeduceResults); + Expr *IsDeducible = buildIsDeducibleConstraint( + SemaRef, AliasTemplate, FPrime->getReturnType(), FPrimeTemplateParams); + Expr *RequiresClause = buildAssociatedConstraints( + SemaRef, F, AliasTemplate, DeduceResults, IsDeducible); // FIXME: implement the is_deducible constraint per C++ // [over.match.class.deduct]p3.3: @@ -5583,6 +5653,8 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, /*UpdateArgsWithConversions=*/false)) return ExprError(); + DiagnoseUseOfDecl(NamedConcept, ConceptNameInfo.getLoc()); + auto *CSD = ImplicitConceptSpecializationDecl::Create( Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(), CanonicalConverted); @@ -6484,7 +6556,8 @@ bool Sema::CheckTemplateArgument( case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: - if (CheckTemplateTemplateArgument(TempParm, Params, Arg)) + if (CheckTemplateTemplateArgument(TempParm, Params, Arg, + /*IsDeduced=*/CTAK != CTAK_Specified)) return true; SugaredConverted.push_back(Arg.getArgument()); @@ -8402,7 +8475,8 @@ static void DiagnoseTemplateParameterListArityMismatch( /// It returns true if an error occurred, and false otherwise. bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, TemplateParameterList *Params, - TemplateArgumentLoc &Arg) { + TemplateArgumentLoc &Arg, + bool IsDeduced) { TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern(); TemplateDecl *Template = Name.getAsTemplateDecl(); if (!Template) { @@ -8454,8 +8528,8 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, !Template->hasAssociatedConstraints()) return false; - if (isTemplateTemplateParameterAtLeastAsSpecializedAs(Params, Template, - Arg.getLocation())) { + if (isTemplateTemplateParameterAtLeastAsSpecializedAs( + Params, Template, Arg.getLocation(), IsDeduced)) { // P2113 // C++20[temp.func.order]p2 // [...] If both deductions succeed, the partial ordering selects the @@ -9787,7 +9861,8 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S, Decl *Sema::ActOnConceptDefinition( Scope *S, MultiTemplateParamsArg TemplateParameterLists, - const IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr) { + const IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr, + const ParsedAttributesView &Attrs) { DeclContext *DC = CurContext; if (!DC->getRedeclContext()->isFileContext()) { @@ -9849,6 +9924,9 @@ Decl *Sema::ActOnConceptDefinition( ActOnDocumentableDecl(NewDecl); if (AddToScope) PushOnScopeChains(NewDecl, S); + + ProcessDeclAttributeList(S, NewDecl, Attrs); + return NewDecl; } @@ -10422,7 +10500,7 @@ bool Sema::CheckFunctionTemplateSpecialization( // specialization, with the template arguments from the previous // specialization. // Take copies of (semantic and syntactic) template argument lists. - const TemplateArgumentList *TemplArgs = TemplateArgumentList::CreateCopy( + TemplateArgumentList *TemplArgs = TemplateArgumentList::CreateCopy( Context, Specialization->getTemplateSpecializationArgs()->asArray()); FD->setFunctionTemplateSpecialization( Specialization->getPrimaryTemplate(), TemplArgs, /*InsertPos=*/nullptr, @@ -11046,8 +11124,7 @@ DeclResult Sema::ActOnExplicitInstantiation( Def->setTemplateSpecializationKind(TSK); if (!getDLLAttr(Def) && getDLLAttr(Specialization) && - (Context.getTargetInfo().shouldDLLImportComdatSymbols() && - !Context.getTargetInfo().getTriple().isPS())) { + Context.getTargetInfo().shouldDLLImportComdatSymbols()) { // An explicit instantiation definition can add a dll attribute to a // template with a previous instantiation declaration. MinGW doesn't // allow this. @@ -11064,8 +11141,7 @@ DeclResult Sema::ActOnExplicitInstantiation( bool NewlyDLLExported = !PreviouslyDLLExported && Specialization->hasAttr(); if (Old_TSK == TSK_ImplicitInstantiation && NewlyDLLExported && - (Context.getTargetInfo().shouldDLLImportComdatSymbols() && - !Context.getTargetInfo().getTriple().isPS())) { + Context.getTargetInfo().shouldDLLImportComdatSymbols()) { // An explicit instantiation definition can add a dll attribute to a // template with a previous implicit instantiation. MinGW doesn't allow // this. We limit clang to only adding dllexport, to avoid potentially diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 853c0e1b50619e2decf6b59e49a948c8ab23bfab..41fd210f29d097ca6fb22fc73097400aea73bb1d 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -139,13 +139,15 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( SmallVectorImpl &Deduced, unsigned TDF, bool PartialOrdering = false, bool DeducedFromArrayBound = false); +enum class PackFold { ParameterToArgument, ArgumentToParameter }; static TemplateDeductionResult DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, ArrayRef Ps, ArrayRef As, TemplateDeductionInfo &Info, SmallVectorImpl &Deduced, - bool NumberOfArgumentsMustMatch); + bool NumberOfArgumentsMustMatch, + PackFold PackFold = PackFold::ParameterToArgument); static void MarkUsedTemplateParameters(ASTContext &Ctx, const TemplateArgument &TemplateArg, @@ -2550,7 +2552,9 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, ArrayRef As, TemplateDeductionInfo &Info, SmallVectorImpl &Deduced, - bool NumberOfArgumentsMustMatch) { + bool NumberOfArgumentsMustMatch, PackFold PackFold) { + if (PackFold == PackFold::ArgumentToParameter) + std::swap(Ps, As); // C++0x [temp.deduct.type]p9: // If the template argument list of P contains a pack expansion that is not // the last template argument, the entire template argument list is a @@ -2581,8 +2585,11 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, return TemplateDeductionResult::MiscellaneousDeductionFailure; // Perform deduction for this Pi/Ai pair. - if (auto Result = DeduceTemplateArguments(S, TemplateParams, P, - As[ArgIdx], Info, Deduced); + TemplateArgument Pi = P, Ai = As[ArgIdx]; + if (PackFold == PackFold::ArgumentToParameter) + std::swap(Pi, Ai); + if (auto Result = + DeduceTemplateArguments(S, TemplateParams, Pi, Ai, Info, Deduced); Result != TemplateDeductionResult::Success) return Result; @@ -2609,9 +2616,12 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, for (; hasTemplateArgumentForDeduction(As, ArgIdx) && PackScope.hasNextElement(); ++ArgIdx) { + TemplateArgument Pi = Pattern, Ai = As[ArgIdx]; + if (PackFold == PackFold::ArgumentToParameter) + std::swap(Pi, Ai); // Deduce template arguments from the pattern. - if (auto Result = DeduceTemplateArguments(S, TemplateParams, Pattern, - As[ArgIdx], Info, Deduced); + if (auto Result = + DeduceTemplateArguments(S, TemplateParams, Pi, Ai, Info, Deduced); Result != TemplateDeductionResult::Success) return Result; @@ -3237,6 +3247,40 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction( return TemplateDeductionResult::Success; } +/// Complete template argument deduction for DeduceTemplateArgumentsFromType. +/// FIXME: this is mostly duplicated with the above two versions. Deduplicate +/// the three implementations. +static TemplateDeductionResult FinishTemplateArgumentDeduction( + Sema &S, TemplateDecl *TD, + SmallVectorImpl &Deduced, + TemplateDeductionInfo &Info) { + // Unevaluated SFINAE context. + EnterExpressionEvaluationContext Unevaluated( + S, Sema::ExpressionEvaluationContext::Unevaluated); + Sema::SFINAETrap Trap(S); + + Sema::ContextRAII SavedContext(S, getAsDeclContextOrEnclosing(TD)); + + // C++ [temp.deduct.type]p2: + // [...] or if any template argument remains neither deduced nor + // explicitly specified, template argument deduction fails. + SmallVector SugaredBuilder, CanonicalBuilder; + if (auto Result = ConvertDeducedTemplateArguments( + S, TD, /*IsPartialOrdering=*/false, Deduced, Info, SugaredBuilder, + CanonicalBuilder); + Result != TemplateDeductionResult::Success) + return Result; + + if (Trap.hasErrorOccurred()) + return TemplateDeductionResult::SubstitutionFailure; + + if (auto Result = CheckDeducedArgumentConstraints(S, TD, SugaredBuilder, + CanonicalBuilder, Info); + Result != TemplateDeductionResult::Success) + return Result; + + return TemplateDeductionResult::Success; +} /// Perform template argument deduction to determine whether the given template /// arguments match the given class or variable template partial specialization @@ -3305,6 +3349,58 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial, return ::DeduceTemplateArguments(*this, Partial, TemplateArgs, Info); } +TemplateDeductionResult +Sema::DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType, + sema::TemplateDeductionInfo &Info) { + if (TD->isInvalidDecl()) + return TemplateDeductionResult::Invalid; + + QualType PType; + if (const auto *CTD = dyn_cast(TD)) { + // Use the InjectedClassNameType. + PType = Context.getTypeDeclType(CTD->getTemplatedDecl()); + } else if (const auto *AliasTemplate = dyn_cast(TD)) { + PType = AliasTemplate->getTemplatedDecl() + ->getUnderlyingType() + .getCanonicalType(); + } else { + assert(false && "Expected a class or alias template"); + } + + // Unevaluated SFINAE context. + EnterExpressionEvaluationContext Unevaluated( + *this, Sema::ExpressionEvaluationContext::Unevaluated); + SFINAETrap Trap(*this); + + // This deduction has no relation to any outer instantiation we might be + // performing. + LocalInstantiationScope InstantiationScope(*this); + + SmallVector Deduced( + TD->getTemplateParameters()->size()); + SmallVector PArgs = {TemplateArgument(PType)}; + SmallVector AArgs = {TemplateArgument(FromType)}; + if (auto DeducedResult = DeduceTemplateArguments( + TD->getTemplateParameters(), PArgs, AArgs, Info, Deduced, false); + DeducedResult != TemplateDeductionResult::Success) { + return DeducedResult; + } + + SmallVector DeducedArgs(Deduced.begin(), Deduced.end()); + InstantiatingTemplate Inst(*this, Info.getLocation(), TD, DeducedArgs, Info); + if (Inst.isInvalid()) + return TemplateDeductionResult::InstantiationDepth; + + if (Trap.hasErrorOccurred()) + return TemplateDeductionResult::SubstitutionFailure; + + TemplateDeductionResult Result; + runWithSufficientStackSpace(Info.getLocation(), [&] { + Result = ::FinishTemplateArgumentDeduction(*this, TD, Deduced, Info); + }); + return Result; +} + /// Determine whether the given type T is a simple-template-id type. static bool isSimpleTemplateIdType(QualType T) { if (const TemplateSpecializationType *Spec @@ -5453,7 +5549,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, SourceLocation Loc, // is used. if (DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, FD2->getType(), FD1->getType(), Info, Deduced, - TDF_None, + TDF_AllowCompatibleFunctionType, /*PartialOrdering=*/true) != TemplateDeductionResult::Success) return false; break; @@ -5485,20 +5581,40 @@ static bool isAtLeastAsSpecializedAs(Sema &S, SourceLocation Loc, switch (TPOC) { case TPOC_Call: for (unsigned I = 0, N = Args2.size(); I != N; ++I) - ::MarkUsedTemplateParameters(S.Context, Args2[I], false, - TemplateParams->getDepth(), - UsedParameters); + ::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false, + TemplateParams->getDepth(), UsedParameters); break; case TPOC_Conversion: - ::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false, + ::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), + /*OnlyDeduced=*/false, TemplateParams->getDepth(), UsedParameters); break; case TPOC_Other: - ::MarkUsedTemplateParameters(S.Context, FD2->getType(), false, - TemplateParams->getDepth(), - UsedParameters); + // We do not deduce template arguments from the exception specification + // when determining the primary template of a function template + // specialization or when taking the address of a function template. + // Therefore, we do not mark template parameters in the exception + // specification as used during partial ordering to prevent the following + // from being ambiguous: + // + // template + // void f(U) noexcept(noexcept(T())); // #1 + // + // template + // void f(T*) noexcept; // #2 + // + // template<> + // void f(int*) noexcept; // explicit specialization of #2 + // + // Although there is no corresponding wording in the standard, this seems + // to be the intended behavior given the definition of + // 'deduction substitution loci' in [temp.deduct]. + ::MarkUsedTemplateParameters( + S.Context, + S.Context.getFunctionTypeWithExceptionSpec(FD2->getType(), EST_None), + /*OnlyDeduced=*/false, TemplateParams->getDepth(), UsedParameters); break; } @@ -5522,7 +5638,8 @@ static bool isAtLeastAsSpecializedAs(Sema &S, SourceLocation Loc, /// function templates. /// /// \param NumCallArguments1 The number of arguments in the call to FT1, used -/// only when \c TPOC is \c TPOC_Call. +/// only when \c TPOC is \c TPOC_Call. Does not include the object argument when +/// calling a member function. /// /// \param RawObj1Ty The type of the object parameter of FT1 if a member /// function only used if \c TPOC is \c TPOC_Call and FT1 is a Function @@ -5591,7 +5708,11 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate( IsRValRef1); Args2.push_back(Obj2Ty); } - size_t NumComparedArguments = NumCallArguments1 + ShouldConvert1; + size_t NumComparedArguments = NumCallArguments1; + // Either added an argument above or the prototype includes an explicit + // object argument we need to count + if (Method1) + ++NumComparedArguments; Args1.insert(Args1.end(), Proto1->param_type_begin(), Proto1->param_type_end()); @@ -6193,7 +6314,8 @@ bool Sema::isMoreSpecializedThanPrimary( } bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs( - TemplateParameterList *P, TemplateDecl *AArg, SourceLocation Loc) { + TemplateParameterList *P, TemplateDecl *AArg, SourceLocation Loc, + bool IsDeduced) { // C++1z [temp.arg.template]p4: (DR 150) // A template template-parameter P is at least as specialized as a // template template-argument A if, given the following rewrite to two @@ -6203,11 +6325,10 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs( // equivalent partial ordering by performing deduction directly on // the template parameter lists of the template template parameters. // - // Given an invented class template X with the template parameter list of - // A (including default arguments): - TemplateName X = Context.getCanonicalTemplateName(TemplateName(AArg)); TemplateParameterList *A = AArg->getTemplateParameters(); + // Given an invented class template X with the template parameter list of + // A (including default arguments): // - Each function template has a single function parameter whose type is // a specialization of X with template arguments corresponding to the // template parameters from the respective function template @@ -6250,14 +6371,43 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs( return false; } - QualType AType = Context.getCanonicalTemplateSpecializationType(X, AArgs); - QualType PType = Context.getCanonicalTemplateSpecializationType(X, PArgs); + // Determine whether P1 is at least as specialized as P2. + TemplateDeductionInfo Info(Loc, A->getDepth()); + SmallVector Deduced; + Deduced.resize(A->size()); // ... the function template corresponding to P is at least as specialized // as the function template corresponding to A according to the partial // ordering rules for function templates. - TemplateDeductionInfo Info(Loc, A->getDepth()); - return isAtLeastAsSpecializedAs(*this, PType, AType, AArg, Info); + + // Provisional resolution for CWG2398: Regarding temp.arg.template]p4, when + // applying the partial ordering rules for function templates on + // the rewritten template template parameters: + // - In a deduced context, the matching of packs versus fixed-size needs to + // be inverted between Ps and As. On non-deduced context, matching needs to + // happen both ways, according to [temp.arg.template]p3, but this is + // currently implemented as a special case elsewhere. + if (::DeduceTemplateArguments(*this, A, AArgs, PArgs, Info, Deduced, + /*NumberOfArgumentsMustMatch=*/false, + IsDeduced ? PackFold::ArgumentToParameter + : PackFold::ParameterToArgument) != + TemplateDeductionResult::Success) + return false; + + SmallVector DeducedArgs(Deduced.begin(), Deduced.end()); + Sema::InstantiatingTemplate Inst(*this, Info.getLocation(), AArg, DeducedArgs, + Info); + if (Inst.isInvalid()) + return false; + + bool AtLeastAsSpecialized; + runWithSufficientStackSpace(Info.getLocation(), [&] { + AtLeastAsSpecialized = + ::FinishTemplateArgumentDeduction( + *this, AArg, /*IsPartialOrdering=*/true, PArgs, Deduced, Info) == + TemplateDeductionResult::Success; + }); + return AtLeastAsSpecialized; } namespace { diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index eb67546d048ae088064dc8f1c002f2c67c42f884..c19c8cc34dd3bdad1d4eea8c97ce9efea729d707 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -3257,9 +3257,13 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, Info = &SemaRef.InventedParameterInfos.back(); } else { // In C++14, generic lambdas allow 'auto' in their parameters. - if (!SemaRef.getLangOpts().CPlusPlus14 || !Auto || - Auto->getKeyword() != AutoTypeKeyword::Auto) { - Error = 16; + if (!SemaRef.getLangOpts().CPlusPlus14 && Auto && + Auto->getKeyword() == AutoTypeKeyword::Auto) { + Error = 25; // auto not allowed in lambda parameter (before C++14) + break; + } else if (!Auto || Auto->getKeyword() != AutoTypeKeyword::Auto) { + Error = 16; // __auto_type or decltype(auto) not allowed in lambda + // parameter break; } Info = SemaRef.getCurLambda(); @@ -6388,6 +6392,11 @@ TypeResult Sema::ActOnTypeName(Declarator &D) { CheckExtraCXXDefaultArguments(D); } + if (const AutoType *AutoT = T->getAs()) + CheckConstrainedAuto( + AutoT, + TInfo->getTypeLoc().getContainedAutoTypeLoc().getConceptNameLoc()); + return CreateParsedType(T, TInfo); } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index c039b95293af2b86a05bea628d698d31cb909419..f9fec21bf5bb604422a32aa4c7089cf43debd970 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4818,14 +4818,6 @@ bool TreeTransform::TransformTemplateArguments( TemplateArgumentLoc In = *First; if (In.getArgument().getKind() == TemplateArgument::Pack) { - // When building the deduction guides, we rewrite the argument packs - // instead of unpacking. - if (getSema().CodeSynthesisContexts.back().Kind == - Sema::CodeSynthesisContext::BuildingDeductionGuides) { - if (getDerived().TransformTemplateArgument(In, Out, Uneval)) - return true; - continue; - } // Unpack argument packs, which we translate them into separate // arguments. // FIXME: We could do much better if we could guarantee that the @@ -16236,10 +16228,11 @@ ExprResult TreeTransform::RebuildCXXOperatorCallExpr( return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, First); } } else { - if (!First->getType()->isOverloadableType() && + if (!First->isTypeDependent() && !Second->isTypeDependent() && + !First->getType()->isOverloadableType() && !Second->getType()->isOverloadableType()) { - // Neither of the arguments is an overloadable type, so try to - // create a built-in binary operation. + // Neither of the arguments is type-dependent or has an overloadable + // type, so try to create a built-in binary operation. BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op); ExprResult Result = SemaRef.CreateBuiltinBinOp(OpLoc, Opc, First, Second); @@ -16250,12 +16243,8 @@ ExprResult TreeTransform::RebuildCXXOperatorCallExpr( } } - // Add any functions found via argument-dependent lookup. - Expr *Args[2] = { First, Second }; - unsigned NumArgs = 1 + (Second != nullptr); - // Create the overloaded operator invocation for unary operators. - if (NumArgs == 1 || isPostIncDec) { + if (!Second || isPostIncDec) { UnaryOperatorKind Opc = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec); return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, First, @@ -16264,8 +16253,8 @@ ExprResult TreeTransform::RebuildCXXOperatorCallExpr( // Create the overloaded operator invocation for binary operators. BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op); - ExprResult Result = SemaRef.CreateOverloadedBinOp( - OpLoc, Opc, Functions, Args[0], Args[1], RequiresADL); + ExprResult Result = SemaRef.CreateOverloadedBinOp(OpLoc, Opc, Functions, + First, Second, RequiresADL); if (Result.isInvalid()) return ExprError(); diff --git a/clang/lib/Serialization/ASTCommon.h b/clang/lib/Serialization/ASTCommon.h index 296642e3674a49d4ac2855071e579ac24999f2ef..0230908d3e0528e30cdfb219fac1a99b1eeb3df9 100644 --- a/clang/lib/Serialization/ASTCommon.h +++ b/clang/lib/Serialization/ASTCommon.h @@ -46,30 +46,6 @@ enum DeclUpdateKind { TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT); -template -TypeID MakeTypeID(ASTContext &Context, QualType T, IdxForTypeTy IdxForType) { - if (T.isNull()) - return PREDEF_TYPE_NULL_ID; - - unsigned FastQuals = T.getLocalFastQualifiers(); - T.removeLocalFastQualifiers(); - - if (T.hasLocalNonFastQualifiers()) - return IdxForType(T).asTypeID(FastQuals); - - assert(!T.hasLocalQualifiers()); - - if (const BuiltinType *BT = dyn_cast(T.getTypePtr())) - return TypeIdxFromBuiltin(BT).asTypeID(FastQuals); - - if (T == Context.AutoDeductTy) - return TypeIdx(PREDEF_TYPE_AUTO_DEDUCT).asTypeID(FastQuals); - if (T == Context.AutoRRefDeductTy) - return TypeIdx(PREDEF_TYPE_AUTO_RREF_DEDUCT).asTypeID(FastQuals); - - return IdxForType(T).asTypeID(FastQuals); -} - unsigned ComputeHash(Selector Sel); /// Retrieve the "definitive" declaration that provides all of the diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 510f61d9cccd8d04c5230b95363095aaa244d618..f50f9569c0a5ee6fe7da6037406409ea24469c15 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -1649,8 +1649,7 @@ bool ASTReader::ReadSLocEntry(int ID) { FileCharacter = (SrcMgr::CharacteristicKind)Record[2]; FileID FID = SourceMgr.createFileID(*File, IncludeLoc, FileCharacter, ID, BaseOffset + Record[0]); - SrcMgr::FileInfo &FileInfo = - const_cast(SourceMgr.getSLocEntry(FID).getFile()); + SrcMgr::FileInfo &FileInfo = SourceMgr.getSLocEntry(FID).getFile(); FileInfo.NumCreatedFIDs = Record[5]; if (Record[3]) FileInfo.setHasLineDirectives(); @@ -1693,8 +1692,7 @@ bool ASTReader::ReadSLocEntry(int ID) { FileID FID = SourceMgr.createFileID(std::move(Buffer), FileCharacter, ID, BaseOffset + Offset, IncludeLoc); if (Record[3]) { - auto &FileInfo = - const_cast(SourceMgr.getSLocEntry(FID).getFile()); + auto &FileInfo = SourceMgr.getSLocEntry(FID).getFile(); FileInfo.setHasLineDirectives(); } break; diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 0c647086e304a32d1b5b073c4c5f0679a1a5914d..a6254b70560c365025028a7693c52587ca4db6e0 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -4186,12 +4186,35 @@ void ASTReader::PassInterestingDeclsToConsumer() { GetDecl(ID); EagerlyDeserializedDecls.clear(); - while (!PotentiallyInterestingDecls.empty()) { - Decl *D = PotentiallyInterestingDecls.front(); - PotentiallyInterestingDecls.pop_front(); + auto ConsumingPotentialInterestingDecls = [this]() { + while (!PotentiallyInterestingDecls.empty()) { + Decl *D = PotentiallyInterestingDecls.front(); + PotentiallyInterestingDecls.pop_front(); + if (isConsumerInterestedIn(D)) + PassInterestingDeclToConsumer(D); + } + }; + std::deque MaybeInterestingDecls = + std::move(PotentiallyInterestingDecls); + assert(PotentiallyInterestingDecls.empty()); + while (!MaybeInterestingDecls.empty()) { + Decl *D = MaybeInterestingDecls.front(); + MaybeInterestingDecls.pop_front(); + // Since we load the variable's initializers lazily, it'd be problematic + // if the initializers dependent on each other. So here we try to load the + // initializers of static variables to make sure they are passed to code + // generator by order. If we read anything interesting, we would consume + // that before emitting the current declaration. + if (auto *VD = dyn_cast(D); + VD && VD->isFileVarDecl() && !VD->isExternallyVisible()) + VD->getInit(); + ConsumingPotentialInterestingDecls(); if (isConsumerInterestedIn(D)) PassInterestingDeclToConsumer(D); } + + // If we add any new potential interesting decl in the last call, consume it. + ConsumingPotentialInterestingDecls(); } void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 129bc337c8924acd7735e82e479a534d49939034..1d6d96932ba2cfd2c309fe260b7fb59b0a5ab6e1 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1460,7 +1460,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, (!PP.getHeaderSearchInfo() .getHeaderSearchOpts() .ModuleMapFileHomeIsCwd || - WritingModule->Directory->getName() != StringRef("."))) { + WritingModule->Directory->getName() != ".")) { // Module directory. auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(MODULE_DIRECTORY)); @@ -3304,7 +3304,7 @@ static bool IsInternalDeclFromFileContext(const Decl *D) { /// \returns the offset of the DECL_CONTEXT_LEXICAL block within the /// bitstream, or 0 if no block was written. uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, - DeclContext *DC) { + const DeclContext *DC) { if (DC->decls_empty()) return 0; @@ -5698,8 +5698,8 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { break; case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: - Record.AddStmt(const_cast( - cast(Update.getDecl())->getDefaultArg())); + Record.writeStmtRef( + cast(Update.getDecl())->getDefaultArg()); break; case UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER: @@ -5713,8 +5713,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { Record.push_back(RD->isParamDestroyedInCallee()); Record.push_back(llvm::to_underlying(RD->getArgPassingRestrictions())); Record.AddCXXDefinitionData(RD); - Record.AddOffset(WriteDeclContextLexicalBlock( - *Context, const_cast(RD))); + Record.AddOffset(WriteDeclContextLexicalBlock(*Context, RD)); // This state is sometimes updated by template instantiation, when we // switch from the specialization referring to the template declaration @@ -6075,6 +6074,31 @@ void ASTWriter::AddTypeRef(QualType T, RecordDataImpl &Record) { Record.push_back(GetOrCreateTypeID(T)); } +template +static TypeID MakeTypeID(ASTContext &Context, QualType T, + IdxForTypeTy IdxForType) { + if (T.isNull()) + return PREDEF_TYPE_NULL_ID; + + unsigned FastQuals = T.getLocalFastQualifiers(); + T.removeLocalFastQualifiers(); + + if (T.hasLocalNonFastQualifiers()) + return IdxForType(T).asTypeID(FastQuals); + + assert(!T.hasLocalQualifiers()); + + if (const BuiltinType *BT = dyn_cast(T.getTypePtr())) + return TypeIdxFromBuiltin(BT).asTypeID(FastQuals); + + if (T == Context.AutoDeductTy) + return TypeIdx(PREDEF_TYPE_AUTO_DEDUCT).asTypeID(FastQuals); + if (T == Context.AutoRRefDeductTy) + return TypeIdx(PREDEF_TYPE_AUTO_RREF_DEDUCT).asTypeID(FastQuals); + + return IdxForType(T).asTypeID(FastQuals); +} + TypeID ASTWriter::GetOrCreateTypeID(QualType T) { assert(Context); return MakeTypeID(*Context, T, [&](QualType T) -> TypeIdx { @@ -6098,19 +6122,6 @@ TypeID ASTWriter::GetOrCreateTypeID(QualType T) { }); } -TypeID ASTWriter::getTypeID(QualType T) const { - assert(Context); - return MakeTypeID(*Context, T, [&](QualType T) -> TypeIdx { - if (T.isNull()) - return TypeIdx(); - assert(!T.getLocalFastQualifiers()); - - TypeIdxMap::const_iterator I = TypeIdxs.find(T); - assert(I != TypeIdxs.end() && "Type not emitted!"); - return I->second; - }); -} - void ASTWriter::AddEmittedDeclRef(const Decl *D, RecordDataImpl &Record) { if (!wasDeclEmitted(D)) return; @@ -6357,7 +6368,7 @@ void ASTRecordWriter::AddTemplateParameterList( AddDeclRef(P); if (const Expr *RequiresClause = TemplateParams->getRequiresClause()) { Record->push_back(true); - AddStmt(const_cast(RequiresClause)); + writeStmtRef(RequiresClause); } else { Record->push_back(false); } @@ -7814,7 +7825,7 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { case OpenACCClauseKind::If: { const auto *IC = cast(C); writeSourceLocation(IC->getLParenLoc()); - AddStmt(const_cast(IC->getConditionExpr())); + writeStmtRef(IC->getConditionExpr()); return; } case OpenACCClauseKind::Self: { @@ -7822,7 +7833,7 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { writeSourceLocation(SC->getLParenLoc()); writeBool(SC->hasConditionExpr()); if (SC->hasConditionExpr()) - AddStmt(const_cast(SC->getConditionExpr())); + writeStmtRef(SC->getConditionExpr()); return; } case OpenACCClauseKind::NumGangs: { @@ -7836,13 +7847,13 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { case OpenACCClauseKind::NumWorkers: { const auto *NWC = cast(C); writeSourceLocation(NWC->getLParenLoc()); - AddStmt(const_cast(NWC->getIntExpr())); + writeStmtRef(NWC->getIntExpr()); return; } case OpenACCClauseKind::VectorLength: { const auto *NWC = cast(C); writeSourceLocation(NWC->getLParenLoc()); - AddStmt(const_cast(NWC->getIntExpr())); + writeStmtRef(NWC->getIntExpr()); return; } case OpenACCClauseKind::Private: { @@ -7921,7 +7932,7 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { writeSourceLocation(AC->getLParenLoc()); writeBool(AC->hasIntExpr()); if (AC->hasIntExpr()) - AddStmt(const_cast(AC->getIntExpr())); + writeStmtRef(AC->getIntExpr()); return; } case OpenACCClauseKind::Wait: { @@ -7929,7 +7940,7 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { writeSourceLocation(WC->getLParenLoc()); writeBool(WC->getDevNumExpr()); if (const Expr *DNE = WC->getDevNumExpr()) - AddStmt(const_cast(DNE)); + writeStmtRef(DNE); writeSourceLocation(WC->getQueuesLoc()); writeOpenACCIntExprList(WC->getQueueIdExprs()); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 39aec31b6d87900d95e8afa5aa7e4e993b0799f6..6f7c368ce9ca43bbc8434529f0e94f958f0c33b1 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -473,7 +473,7 @@ addConstraintSatisfaction(ASTRecordWriter &Record, if (!Satisfaction.IsSatisfied) { Record.push_back(Satisfaction.NumRecords); for (const auto &DetailRecord : Satisfaction) { - Record.AddStmt(const_cast(DetailRecord.first)); + Record.writeStmtRef(DetailRecord.first); auto *E = DetailRecord.second.dyn_cast(); Record.push_back(E == nullptr); if (E) diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp index a0190c30bfd28aa9ddfe1bf2b4f7c498be26dc6c..eb40a4cd3d90242b1141413ec6cff004d4d45869 100644 --- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp @@ -400,17 +400,14 @@ private: void taintUnsafeSocketProtocol(const CallEvent &Call, CheckerContext &C) const; - /// Default taint rules are initalized with the help of a CheckerContext to - /// access the names of built-in functions like memcpy. + /// The taint rules are initalized with the help of a CheckerContext to + /// access user-provided configuration. void initTaintRules(CheckerContext &C) const; - /// CallDescription currently cannot restrict matches to the global namespace - /// only, which is why multiple CallDescriptionMaps are used, as we want to - /// disambiguate global C functions from functions inside user-defined - /// namespaces. - // TODO: Remove separation to simplify matching logic once CallDescriptions - // are more expressive. - + // TODO: The two separate `CallDescriptionMap`s were introduced when + // `CallDescription` was unable to restrict matches to the global namespace + // only. This limitation no longer exists, so the following two maps should + // be unified. mutable std::optional StaticTaintRules; mutable std::optional DynamicTaintRules; }; @@ -506,7 +503,8 @@ void GenericTaintRuleParser::consumeRulesFromConfig(const Config &C, GenericTaintRule &&Rule, RulesContTy &Rules) { NamePartsTy NameParts = parseNameParts(C); - Rules.emplace_back(CallDescription(NameParts), std::move(Rule)); + Rules.emplace_back(CallDescription(CDM::Unspecified, NameParts), + std::move(Rule)); } void GenericTaintRuleParser::parseConfig(const std::string &Option, @@ -572,196 +570,236 @@ void GenericTaintChecker::initTaintRules(CheckerContext &C) const { std::vector>; using TR = GenericTaintRule; - const Builtin::Context &BI = C.getASTContext().BuiltinInfo; - RulesConstructionTy GlobalCRules{ // Sources - {{{"fdopen"}}, TR::Source({{ReturnValueIndex}})}, - {{{"fopen"}}, TR::Source({{ReturnValueIndex}})}, - {{{"freopen"}}, TR::Source({{ReturnValueIndex}})}, - {{{"getch"}}, TR::Source({{ReturnValueIndex}})}, - {{{"getchar"}}, TR::Source({{ReturnValueIndex}})}, - {{{"getchar_unlocked"}}, TR::Source({{ReturnValueIndex}})}, - {{{"gets"}}, TR::Source({{0}, ReturnValueIndex})}, - {{{"gets_s"}}, TR::Source({{0}, ReturnValueIndex})}, - {{{"scanf"}}, TR::Source({{}, 1})}, - {{{"scanf_s"}}, TR::Source({{}, {1}})}, - {{{"wgetch"}}, TR::Source({{}, ReturnValueIndex})}, + {{CDM::CLibrary, {"fdopen"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"fopen"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"freopen"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"getch"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"getchar"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"getchar_unlocked"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"gets"}}, TR::Source({{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {"gets_s"}}, TR::Source({{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {"scanf"}}, TR::Source({{}, 1})}, + {{CDM::CLibrary, {"scanf_s"}}, TR::Source({{}, 1})}, + {{CDM::CLibrary, {"wgetch"}}, TR::Source({{ReturnValueIndex}})}, // Sometimes the line between taint sources and propagators is blurry. // _IO_getc is choosen to be a source, but could also be a propagator. // This way it is simpler, as modeling it as a propagator would require // to model the possible sources of _IO_FILE * values, which the _IO_getc // function takes as parameters. - {{{"_IO_getc"}}, TR::Source({{ReturnValueIndex}})}, - {{{"getcwd"}}, TR::Source({{0, ReturnValueIndex}})}, - {{{"getwd"}}, TR::Source({{0, ReturnValueIndex}})}, - {{{"readlink"}}, TR::Source({{1, ReturnValueIndex}})}, - {{{"readlinkat"}}, TR::Source({{2, ReturnValueIndex}})}, - {{{"get_current_dir_name"}}, TR::Source({{ReturnValueIndex}})}, - {{{"gethostname"}}, TR::Source({{0}})}, - {{{"getnameinfo"}}, TR::Source({{2, 4}})}, - {{{"getseuserbyname"}}, TR::Source({{1, 2}})}, - {{{"getgroups"}}, TR::Source({{1, ReturnValueIndex}})}, - {{{"getlogin"}}, TR::Source({{ReturnValueIndex}})}, - {{{"getlogin_r"}}, TR::Source({{0}})}, + {{CDM::CLibrary, {"_IO_getc"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"getcwd"}}, TR::Source({{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {"getwd"}}, TR::Source({{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {"readlink"}}, TR::Source({{1, ReturnValueIndex}})}, + {{CDM::CLibrary, {"readlinkat"}}, TR::Source({{2, ReturnValueIndex}})}, + {{CDM::CLibrary, {"get_current_dir_name"}}, + TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"gethostname"}}, TR::Source({{0}})}, + {{CDM::CLibrary, {"getnameinfo"}}, TR::Source({{2, 4}})}, + {{CDM::CLibrary, {"getseuserbyname"}}, TR::Source({{1, 2}})}, + {{CDM::CLibrary, {"getgroups"}}, TR::Source({{1, ReturnValueIndex}})}, + {{CDM::CLibrary, {"getlogin"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"getlogin_r"}}, TR::Source({{0}})}, // Props - {{{"accept"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"atoi"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"atol"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"atoll"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"fgetc"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"fgetln"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"fgets"}}, TR::Prop({{2}}, {{0, ReturnValueIndex}})}, - {{{"fgetws"}}, TR::Prop({{2}}, {{0, ReturnValueIndex}})}, - {{{"fscanf"}}, TR::Prop({{0}}, {{}, 2})}, - {{{"fscanf_s"}}, TR::Prop({{0}}, {{}, {2}})}, - {{{"sscanf"}}, TR::Prop({{0}}, {{}, 2})}, - - {{{"getc"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"getc_unlocked"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"getdelim"}}, TR::Prop({{3}}, {{0}})}, - {{{"getline"}}, TR::Prop({{2}}, {{0}})}, - {{{"getw"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"pread"}}, TR::Prop({{0, 1, 2, 3}}, {{1, ReturnValueIndex}})}, - {{{"read"}}, TR::Prop({{0, 2}}, {{1, ReturnValueIndex}})}, - {{{"strchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"strrchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"tolower"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"toupper"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"fread"}}, TR::Prop({{3}}, {{0, ReturnValueIndex}})}, - {{{"recv"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, - {{{"recvfrom"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, - - {{{"ttyname"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"ttyname_r"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, - - {{{"basename"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"dirname"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"fnmatch"}}, TR::Prop({{1}}, {{ReturnValueIndex}})}, - {{{"memchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"memrchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"rawmemchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - - {{{"mbtowc"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - {{{"wctomb"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - {{{"wcwidth"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - - {{{"memcmp"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, - {{{"memcpy"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - {{{"memmove"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - // If memmem was called with a tainted needle and the search was - // successful, that would mean that the value pointed by the return value - // has the same content as the needle. If we choose to go by the policy of - // content equivalence implies taintedness equivalence, that would mean - // haystack should be considered a propagation source argument. - {{{"memmem"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - - // The comment for memmem above also applies to strstr. - {{{"strstr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"strcasestr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - - {{{"strchrnul"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - - {{{"index"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"rindex"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"accept"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"atoi"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"atol"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"atoll"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"fgetc"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"fgetln"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"fgets"}}, + TR::Prop({{2}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"fgetws"}}, + TR::Prop({{2}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {"fscanf"}}, TR::Prop({{0}}, {{}, 2})}, + {{CDM::CLibrary, {"fscanf_s"}}, TR::Prop({{0}}, {{}, 2})}, + {{CDM::CLibrary, {"sscanf"}}, TR::Prop({{0}}, {{}, 2})}, + {{CDM::CLibrary, {"sscanf_s"}}, TR::Prop({{0}}, {{}, 2})}, + + {{CDM::CLibrary, {"getc"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"getc_unlocked"}}, + TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"getdelim"}}, TR::Prop({{3}}, {{0}})}, + // TODO: this intends to match the C function `getline()`, but the call + // description also matches the C++ function `std::getline()`; it should + // be ruled out by some additional logic. + {{CDM::CLibrary, {"getline"}}, TR::Prop({{2}}, {{0}})}, + {{CDM::CLibrary, {"getw"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"pread"}}, + TR::Prop({{0, 1, 2, 3}}, {{1, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"read"}}, + TR::Prop({{0, 2}}, {{1, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"fread"}}, + TR::Prop({{3}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"recv"}}, + TR::Prop({{0}}, {{1, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"recvfrom"}}, + TR::Prop({{0}}, {{1, ReturnValueIndex}})}, + + {{CDM::CLibrary, {"ttyname"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"ttyname_r"}}, + TR::Prop({{0}}, {{1, ReturnValueIndex}})}, + + {{CDM::CLibrary, {"basename"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"dirname"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"fnmatch"}}, TR::Prop({{1}}, {{ReturnValueIndex}})}, + + {{CDM::CLibrary, {"mbtowc"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {"wctomb"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {"wcwidth"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + + {{CDM::CLibrary, {"memcmp"}}, + TR::Prop({{0, 1, 2}}, {{ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"memcpy"}}, + TR::Prop({{1, 2}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"memmove"}}, + TR::Prop({{1, 2}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"bcopy"}}, TR::Prop({{0, 2}}, {{1}})}, + + // Note: "memmem" and its variants search for a byte sequence ("needle") + // in a larger area ("haystack"). Currently we only propagate taint from + // the haystack to the result, but in theory tampering with the needle + // could also produce incorrect results. + {{CDM::CLibrary, {"memmem"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strstr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strcasestr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + + // Analogously, the following functions search for a byte within a buffer + // and we only propagate taint from the buffer to the result. + {{CDM::CLibraryMaybeHardened, {"memchr"}}, + TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"memrchr"}}, + TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"rawmemchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"strchr"}}, + TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"strrchr"}}, + TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"strchrnul"}}, + TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"index"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"rindex"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, // FIXME: In case of arrays, only the first element of the array gets // tainted. - {{{"qsort"}}, TR::Prop({{0}}, {{0}})}, - {{{"qsort_r"}}, TR::Prop({{0}}, {{0}})}, - - {{{"strcmp"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, - {{{"strcasecmp"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, - {{{"strncmp"}}, TR::Prop({{0, 1, 2}}, {{ReturnValueIndex}})}, - {{{"strncasecmp"}}, TR::Prop({{0, 1, 2}}, {{ReturnValueIndex}})}, - {{{"strspn"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, - {{{"strcspn"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, - {{{"strpbrk"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"strndup"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"strndupa"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"qsort"}}, TR::Prop({{0}}, {{0}})}, + {{CDM::CLibrary, {"qsort_r"}}, TR::Prop({{0}}, {{0}})}, + + {{CDM::CLibrary, {"strcmp"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strcasecmp"}}, + TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strncmp"}}, + TR::Prop({{0, 1, 2}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strncasecmp"}}, + TR::Prop({{0, 1, 2}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strspn"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strcspn"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strpbrk"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + + {{CDM::CLibrary, {"strndup"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strndupa"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strdup"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strdupa"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"wcsdup"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, // strlen, wcslen, strnlen and alike intentionally don't propagate taint. // See the details here: https://github.com/llvm/llvm-project/pull/66086 - {{{"strtol"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, - {{{"strtoll"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, - {{{"strtoul"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, - {{{"strtoull"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, - - {{{"isalnum"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isalpha"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isascii"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isblank"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"iscntrl"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isdigit"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isgraph"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"islower"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isprint"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"ispunct"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isspace"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isupper"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isxdigit"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - - {{CDM::CLibraryMaybeHardened, {BI.getName(Builtin::BIstrncat)}}, - TR::Prop({{1, 2}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibraryMaybeHardened, {BI.getName(Builtin::BIstrlcpy)}}, - TR::Prop({{1, 2}}, {{0}})}, - {{CDM::CLibraryMaybeHardened, {BI.getName(Builtin::BIstrlcat)}}, - TR::Prop({{1, 2}}, {{0}})}, - {{CDM::CLibraryMaybeHardened, {{"snprintf"}}}, - TR::Prop({{1}, 3}, {{0, ReturnValueIndex}})}, - {{CDM::CLibraryMaybeHardened, {{"sprintf"}}}, - TR::Prop({{1}, 2}, {{0, ReturnValueIndex}})}, - {{CDM::CLibraryMaybeHardened, {{"strcpy"}}}, + {{CDM::CLibrary, {"strtol"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, + {{CDM::CLibrary, {"strtoll"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, + {{CDM::CLibrary, {"strtoul"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, + {{CDM::CLibrary, {"strtoull"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, + + {{CDM::CLibrary, {"tolower"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"toupper"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + + {{CDM::CLibrary, {"isalnum"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isalpha"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isascii"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isblank"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"iscntrl"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isdigit"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isgraph"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"islower"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isprint"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"ispunct"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isspace"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isupper"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isxdigit"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + + {{CDM::CLibraryMaybeHardened, {"strcpy"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibraryMaybeHardened, {{"stpcpy"}}}, + {{CDM::CLibraryMaybeHardened, {"stpcpy"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibraryMaybeHardened, {{"strcat"}}}, + {{CDM::CLibraryMaybeHardened, {"strcat"}}, TR::Prop({{0, 1}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibraryMaybeHardened, {{"wcsncat"}}}, + {{CDM::CLibraryMaybeHardened, {"wcsncat"}}, TR::Prop({{0, 1}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibrary, {{"strdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{CDM::CLibrary, {{"strdupa"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{CDM::CLibrary, {{"wcsdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{CDM::CLibrary, BI.getName(Builtin::BImemcpy)}, - TR::Prop({{1, 2}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibrary, {BI.getName(Builtin::BImemmove)}}, + {{CDM::CLibraryMaybeHardened, {"strncpy"}}, TR::Prop({{1, 2}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibrary, {BI.getName(Builtin::BIstrncpy)}}, - TR::Prop({{1, 2}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibrary, {BI.getName(Builtin::BIstrndup)}}, - TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, - {{CDM::CLibrary, {"bcopy"}}, TR::Prop({{0, 2}}, {{1}})}, + {{CDM::CLibraryMaybeHardened, {"strncat"}}, + TR::Prop({{0, 1, 2}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"strlcpy"}}, TR::Prop({{1, 2}}, {{0}})}, + {{CDM::CLibraryMaybeHardened, {"strlcat"}}, TR::Prop({{0, 1, 2}}, {{0}})}, + + // Usually the matching mode `CDM::CLibraryMaybeHardened` is sufficient + // for unified handling of a function `FOO()` and its hardened variant + // `__FOO_chk()`, but in the "sprintf" family the extra parameters of the + // hardened variants are inserted into the middle of the parameter list, + // so that would not work in their case. + // int snprintf(char * str, size_t maxlen, const char * format, ...); + {{CDM::CLibrary, {"snprintf"}}, + TR::Prop({{1, 2}, 3}, {{0, ReturnValueIndex}})}, + // int sprintf(char * str, const char * format, ...); + {{CDM::CLibrary, {"sprintf"}}, + TR::Prop({{1}, 2}, {{0, ReturnValueIndex}})}, + // int __snprintf_chk(char * str, size_t maxlen, int flag, size_t strlen, + // const char * format, ...); + {{CDM::CLibrary, {"__snprintf_chk"}}, + TR::Prop({{1, 4}, 5}, {{0, ReturnValueIndex}})}, + // int __sprintf_chk(char * str, int flag, size_t strlen, const char * + // format, ...); + {{CDM::CLibrary, {"__sprintf_chk"}}, + TR::Prop({{3}, 4}, {{0, ReturnValueIndex}})}, // Sinks - {{{"system"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)}, - {{{"popen"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)}, - {{{"execl"}}, TR::Sink({{}, {0}}, MsgSanitizeSystemArgs)}, - {{{"execle"}}, TR::Sink({{}, {0}}, MsgSanitizeSystemArgs)}, - {{{"execlp"}}, TR::Sink({{}, {0}}, MsgSanitizeSystemArgs)}, - {{{"execv"}}, TR::Sink({{0, 1}}, MsgSanitizeSystemArgs)}, - {{{"execve"}}, TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)}, - {{{"fexecve"}}, TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)}, - {{{"execvp"}}, TR::Sink({{0, 1}}, MsgSanitizeSystemArgs)}, - {{{"execvpe"}}, TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)}, - {{{"dlopen"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"system"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"popen"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"execl"}}, TR::Sink({{}, {0}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"execle"}}, TR::Sink({{}, {0}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"execlp"}}, TR::Sink({{}, {0}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"execv"}}, TR::Sink({{0, 1}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"execve"}}, + TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"fexecve"}}, + TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"execvp"}}, TR::Sink({{0, 1}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"execvpe"}}, + TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"dlopen"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)}, // malloc, calloc, alloca, realloc, memccpy // are intentionally not marked as taint sinks because unconditional // reporting for these functions generates many false positives. // These taint sinks should be implemented in other checkers with more // sophisticated sanitation heuristics. - {{{{"setproctitle"}}}, TR::Sink({{0}, 1}, MsgUncontrolledFormatString)}, - {{{{"setproctitle_fast"}}}, + + {{CDM::CLibrary, {"setproctitle"}}, + TR::Sink({{0}, 1}, MsgUncontrolledFormatString)}, + {{CDM::CLibrary, {"setproctitle_fast"}}, TR::Sink({{0}, 1}, MsgUncontrolledFormatString)}}; - // `getenv` returns taint only in untrusted environments. if (TR::UntrustedEnv(C)) { // void setproctitle_init(int argc, char *argv[], char *envp[]) + // TODO: replace `MsgCustomSink` with a message that fits this situation. + GlobalCRules.push_back({{CDM::CLibrary, {"setproctitle_init"}}, + TR::Sink({{1, 2}}, MsgCustomSink)}); + + // `getenv` returns taint only in untrusted environments. GlobalCRules.push_back( - {{{"setproctitle_init"}}, TR::Sink({{1, 2}}, MsgCustomSink)}); - GlobalCRules.push_back({{{"getenv"}}, TR::Source({{ReturnValueIndex}})}); + {{CDM::CLibrary, {"getenv"}}, TR::Source({{ReturnValueIndex}})}); } StaticTaintRules.emplace(std::make_move_iterator(GlobalCRules.begin()), diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp index 950d35a090a3f7cd7346f58b6791d43342cdfeb4..5c797d5233089a58139545f2dd74b7a6f42197f3 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp @@ -525,11 +525,19 @@ bool TrivialFunctionAnalysis::isTrivialImpl( if (!IsNew) return It->second; + TrivialFunctionAnalysisVisitor V(Cache); + + if (auto *CtorDecl = dyn_cast(D)) { + for (auto *CtorInit : CtorDecl->inits()) { + if (!V.Visit(CtorInit->getInit())) + return false; + } + } + const Stmt *Body = D->getBody(); if (!Body) return false; - TrivialFunctionAnalysisVisitor V(Cache); bool Result = V.Visit(Body); if (Result) Cache[D] = true; diff --git a/clang/lib/StaticAnalyzer/Core/CallDescription.cpp b/clang/lib/StaticAnalyzer/Core/CallDescription.cpp index 0bb0fe66e54ff8f25acbc5ca5b051fac8de616b8..cd23b381f879afc90dd325a7976faf637a9120bb 100644 --- a/clang/lib/StaticAnalyzer/Core/CallDescription.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallDescription.cpp @@ -48,13 +48,6 @@ ento::CallDescription::CallDescription(Mode MatchAs, [](StringRef From) { return From.str(); }); } -/// Construct a CallDescription with default flags. -ento::CallDescription::CallDescription(ArrayRef QualifiedName, - MaybeCount RequiredArgs /*= None*/, - MaybeCount RequiredParams /*= None*/) - : CallDescription(Mode::Unspecified, QualifiedName, RequiredArgs, - RequiredParams) {} - bool ento::CallDescription::matches(const CallEvent &Call) const { // FIXME: Add ObjC Message support. if (Call.getKind() == CE_ObjCMessage) diff --git a/clang/lib/Tooling/CMakeLists.txt b/clang/lib/Tooling/CMakeLists.txt index 91e6cbdcbc44f7787cdd418e6f26d2d7b1736b23..93a9e707a134cfc430e2f3af48ef0d8f5bb94d5f 100644 --- a/clang/lib/Tooling/CMakeLists.txt +++ b/clang/lib/Tooling/CMakeLists.txt @@ -9,98 +9,10 @@ add_subdirectory(Core) add_subdirectory(Inclusions) add_subdirectory(Refactoring) add_subdirectory(ASTDiff) -add_subdirectory(DumpTool) add_subdirectory(Syntax) add_subdirectory(DependencyScanning) add_subdirectory(Transformer) -# Replace the last lib component of the current binary directory with include -string(FIND ${CMAKE_CURRENT_BINARY_DIR} "/lib/" PATH_LIB_START REVERSE) -if(PATH_LIB_START EQUAL -1) - message(FATAL_ERROR "Couldn't find lib component in binary directory") -endif() -math(EXPR PATH_LIB_END "${PATH_LIB_START}+5") -string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) -string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} ${PATH_LIB_END} -1 PATH_TAIL) -string(CONCAT BINARY_INCLUDE_DIR ${PATH_HEAD} "/include/clang/" ${PATH_TAIL}) - -if (NOT Python3_EXECUTABLE - OR APPLE - OR CMAKE_CROSSCOMPILING - OR GENERATOR_IS_MULTI_CONFIG - OR NOT LLVM_NATIVE_ARCH IN_LIST LLVM_TARGETS_TO_BUILD - ) - configure_file( - EmptyNodeIntrospection.inc.in - ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc - COPYONLY - ) - set(CLANG_TOOLING_BUILD_AST_INTROSPECTION "OFF" CACHE BOOL "") -else() - # The generation of ASTNodeAPI.json takes a long time in a - # Debug build due to parsing AST.h. Disable the processing - # but setting CLANG_TOOLING_BUILD_AST_INTROSPECTION as an - # internal hidden setting to override. - # When the processing is disabled, a trivial/empty JSON - # file is generated by clang-ast-dump and generate_cxx_src_locs.py - # generates the same API, but with a trivial implementation. - option(CLANG_TOOLING_BUILD_AST_INTROSPECTION "Enable AST introspection" TRUE) - - set(skip_expensive_processing $,$>>) - - set(implicitDirs) - foreach(implicitDir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) - list(APPEND implicitDirs -I ${implicitDir}) - endforeach() - - include(GetClangResourceDir) - get_clang_resource_dir(resource_dir PREFIX ${LLVM_BINARY_DIR}) - add_custom_command( - COMMENT Generate ASTNodeAPI.json - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json - DEPENDS clang-ast-dump clang-resource-headers - COMMAND - $ - # Skip this in debug mode because parsing AST.h is too slow - --skip-processing=${skip_expensive_processing} - -I ${resource_dir}/include - -I ${CLANG_SOURCE_DIR}/include - -I ${LLVM_BINARY_DIR}/tools/clang/include - -I ${LLVM_BINARY_DIR}/include - -I ${LLVM_SOURCE_DIR}/include - ${implicitDirs} - --json-output-path ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json - ) - - add_custom_target(run-ast-api-dump-tool - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json - ) - - add_custom_command( - COMMENT Generate NodeIntrospection.inc - OUTPUT ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json - ${CMAKE_CURRENT_SOURCE_DIR}/DumpTool/generate_cxx_src_locs.py - ${CMAKE_CURRENT_SOURCE_DIR}/EmptyNodeIntrospection.inc.in - COMMAND - ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/DumpTool/generate_cxx_src_locs.py - --json-input-path ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json - --output-file NodeIntrospection.inc - --use-empty-implementation ${skip_expensive_processing} - --empty-implementation - "${CMAKE_CURRENT_SOURCE_DIR}/EmptyNodeIntrospection.inc.in" - COMMAND - ${CMAKE_COMMAND} -E copy_if_different - ${CMAKE_CURRENT_BINARY_DIR}/NodeIntrospection.inc - ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc - ) - - add_custom_target(run-ast-api-generate-tool - DEPENDS - ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc - ) -endif() - add_clang_library(clangTooling AllTUsExecution.cpp ArgumentsAdjusters.cpp @@ -116,8 +28,6 @@ add_clang_library(clangTooling Refactoring.cpp RefactoringCallbacks.cpp StandaloneExecution.cpp - NodeIntrospection.cpp - ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc Tooling.cpp DEPENDS diff --git a/clang/lib/Tooling/DumpTool/APIData.h b/clang/lib/Tooling/DumpTool/APIData.h deleted file mode 100644 index 03e247a8bd955f455f685e3bf182015547b5c2ad..0000000000000000000000000000000000000000 --- a/clang/lib/Tooling/DumpTool/APIData.h +++ /dev/null @@ -1,31 +0,0 @@ -//===- APIData.h ---------------------------------------------*- C++ -*----===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_TOOLING_DUMPTOOL_APIDATA_H -#define LLVM_CLANG_LIB_TOOLING_DUMPTOOL_APIDATA_H - -#include -#include - -namespace clang { -namespace tooling { - -struct ClassData { - std::vector ASTClassLocations; - std::vector ASTClassRanges; - std::vector TemplateParms; - std::vector TypeSourceInfos; - std::vector TypeLocs; - std::vector NestedNameLocs; - std::vector DeclNameInfos; -}; - -} // namespace tooling -} // namespace clang - -#endif diff --git a/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp b/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp deleted file mode 100644 index 42691d556d986f0edce793fe8e9cb805af8ed0fd..0000000000000000000000000000000000000000 --- a/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp +++ /dev/null @@ -1,271 +0,0 @@ -//===- ASTSrcLocProcessor.cpp --------------------------------*- 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 -// -//===----------------------------------------------------------------------===// - -#include "ASTSrcLocProcessor.h" - -#include "clang/Frontend/CompilerInstance.h" -#include "llvm/Support/JSON.h" -#include "llvm/Support/MemoryBuffer.h" - -using namespace clang::tooling; -using namespace llvm; -using namespace clang::ast_matchers; - -ASTSrcLocProcessor::ASTSrcLocProcessor(StringRef JsonPath) - : JsonPath(JsonPath) { - - MatchFinder::MatchFinderOptions FinderOptions; - - Finder = std::make_unique(std::move(FinderOptions)); - Finder->addMatcher( - cxxRecordDecl( - isDefinition(), - isSameOrDerivedFrom( - namedDecl( - hasAnyName( - "clang::Stmt", "clang::Decl", "clang::CXXCtorInitializer", - "clang::NestedNameSpecifierLoc", - "clang::TemplateArgumentLoc", "clang::CXXBaseSpecifier", - "clang::DeclarationNameInfo", "clang::TypeLoc")) - .bind("nodeClade")), - optionally(isDerivedFrom(cxxRecordDecl().bind("derivedFrom")))) - .bind("className"), - this); - Finder->addMatcher( - cxxRecordDecl(isDefinition(), hasAnyName("clang::PointerLikeTypeLoc", - "clang::TypeofLikeTypeLoc")) - .bind("templateName"), - this); -} - -std::unique_ptr -ASTSrcLocProcessor::createASTConsumer(clang::CompilerInstance &Compiler, - StringRef File) { - return Finder->newASTConsumer(); -} - -llvm::json::Object toJSON(llvm::StringMap> const &Obj) { - using llvm::json::toJSON; - - llvm::json::Object JsonObj; - for (const auto &Item : Obj) { - JsonObj[Item.first()] = Item.second; - } - return JsonObj; -} - -llvm::json::Object toJSON(llvm::StringMap const &Obj) { - using llvm::json::toJSON; - - llvm::json::Object JsonObj; - for (const auto &Item : Obj) { - JsonObj[Item.first()] = Item.second; - } - return JsonObj; -} - -llvm::json::Object toJSON(ClassData const &Obj) { - llvm::json::Object JsonObj; - - if (!Obj.ASTClassLocations.empty()) - JsonObj["sourceLocations"] = Obj.ASTClassLocations; - if (!Obj.ASTClassRanges.empty()) - JsonObj["sourceRanges"] = Obj.ASTClassRanges; - if (!Obj.TemplateParms.empty()) - JsonObj["templateParms"] = Obj.TemplateParms; - if (!Obj.TypeSourceInfos.empty()) - JsonObj["typeSourceInfos"] = Obj.TypeSourceInfos; - if (!Obj.TypeLocs.empty()) - JsonObj["typeLocs"] = Obj.TypeLocs; - if (!Obj.NestedNameLocs.empty()) - JsonObj["nestedNameLocs"] = Obj.NestedNameLocs; - if (!Obj.DeclNameInfos.empty()) - JsonObj["declNameInfos"] = Obj.DeclNameInfos; - return JsonObj; -} - -llvm::json::Object toJSON(llvm::StringMap const &Obj) { - using llvm::json::toJSON; - - llvm::json::Object JsonObj; - for (const auto &Item : Obj) - JsonObj[Item.first()] = ::toJSON(Item.second); - return JsonObj; -} - -void WriteJSON(StringRef JsonPath, llvm::json::Object &&ClassInheritance, - llvm::json::Object &&ClassesInClade, - llvm::json::Object &&ClassEntries) { - llvm::json::Object JsonObj; - - using llvm::json::toJSON; - - JsonObj["classInheritance"] = std::move(ClassInheritance); - JsonObj["classesInClade"] = std::move(ClassesInClade); - JsonObj["classEntries"] = std::move(ClassEntries); - - llvm::json::Value JsonVal(std::move(JsonObj)); - - bool WriteChange = false; - std::string OutString; - if (auto ExistingOrErr = MemoryBuffer::getFile(JsonPath, /*IsText=*/true)) { - raw_string_ostream Out(OutString); - Out << formatv("{0:2}", JsonVal); - if (ExistingOrErr.get()->getBuffer() == Out.str()) - return; - WriteChange = true; - } - - std::error_code EC; - llvm::raw_fd_ostream JsonOut(JsonPath, EC, llvm::sys::fs::OF_Text); - if (EC) - return; - - if (WriteChange) - JsonOut << OutString; - else - JsonOut << formatv("{0:2}", JsonVal); -} - -void ASTSrcLocProcessor::generate() { - WriteJSON(JsonPath, ::toJSON(ClassInheritance), ::toJSON(ClassesInClade), - ::toJSON(ClassEntries)); -} - -void ASTSrcLocProcessor::generateEmpty() { WriteJSON(JsonPath, {}, {}, {}); } - -std::vector -CaptureMethods(std::string TypeString, const clang::CXXRecordDecl *ASTClass, - const MatchFinder::MatchResult &Result) { - - auto publicAccessor = [](auto... InnerMatcher) { - return cxxMethodDecl(isPublic(), parameterCountIs(0), isConst(), - InnerMatcher...); - }; - - auto BoundNodesVec = match( - findAll( - publicAccessor( - ofClass(cxxRecordDecl( - equalsNode(ASTClass), - optionally(isDerivedFrom( - cxxRecordDecl(hasAnyName("clang::Stmt", "clang::Decl")) - .bind("stmtOrDeclBase"))), - optionally(isDerivedFrom( - cxxRecordDecl(hasName("clang::Expr")).bind("exprBase"))), - optionally( - isDerivedFrom(cxxRecordDecl(hasName("clang::TypeLoc")) - .bind("typeLocBase"))))), - returns(hasCanonicalType(asString(TypeString)))) - .bind("classMethod")), - *ASTClass, *Result.Context); - - std::vector Methods; - for (const auto &BN : BoundNodesVec) { - if (const auto *Node = BN.getNodeAs("classMethod")) { - const auto *StmtOrDeclBase = - BN.getNodeAs("stmtOrDeclBase"); - const auto *TypeLocBase = - BN.getNodeAs("typeLocBase"); - const auto *ExprBase = BN.getNodeAs("exprBase"); - // The clang AST has several methods on base classes which are overriden - // pseudo-virtually by derived classes. - // We record only the pseudo-virtual methods on the base classes to - // avoid duplication. - if (StmtOrDeclBase && - (Node->getName() == "getBeginLoc" || Node->getName() == "getEndLoc" || - Node->getName() == "getSourceRange")) - continue; - if (ExprBase && Node->getName() == "getExprLoc") - continue; - if (TypeLocBase && Node->getName() == "getLocalSourceRange") - continue; - if ((ASTClass->getName() == "PointerLikeTypeLoc" || - ASTClass->getName() == "TypeofLikeTypeLoc") && - Node->getName() == "getLocalSourceRange") - continue; - Methods.push_back(Node->getName().str()); - } - } - return Methods; -} - -void ASTSrcLocProcessor::run(const MatchFinder::MatchResult &Result) { - - const auto *ASTClass = - Result.Nodes.getNodeAs("className"); - - StringRef CladeName; - if (ASTClass) { - if (const auto *NodeClade = - Result.Nodes.getNodeAs("nodeClade")) - CladeName = NodeClade->getName(); - } else { - ASTClass = Result.Nodes.getNodeAs("templateName"); - CladeName = "TypeLoc"; - } - - StringRef ClassName = ASTClass->getName(); - - ClassData CD; - - CD.ASTClassLocations = - CaptureMethods("class clang::SourceLocation", ASTClass, Result); - CD.ASTClassRanges = - CaptureMethods("class clang::SourceRange", ASTClass, Result); - CD.TypeSourceInfos = - CaptureMethods("class clang::TypeSourceInfo *", ASTClass, Result); - CD.TypeLocs = CaptureMethods("class clang::TypeLoc", ASTClass, Result); - CD.NestedNameLocs = - CaptureMethods("class clang::NestedNameSpecifierLoc", ASTClass, Result); - CD.DeclNameInfos = - CaptureMethods("struct clang::DeclarationNameInfo", ASTClass, Result); - auto DI = CaptureMethods("const struct clang::DeclarationNameInfo &", - ASTClass, Result); - CD.DeclNameInfos.insert(CD.DeclNameInfos.end(), DI.begin(), DI.end()); - - if (const auto *DerivedFrom = - Result.Nodes.getNodeAs("derivedFrom")) { - - if (const auto *Templ = - llvm::dyn_cast( - DerivedFrom)) { - - const auto &TArgs = Templ->getTemplateArgs(); - - SmallString<256> TArgsString; - llvm::raw_svector_ostream OS(TArgsString); - OS << DerivedFrom->getName() << '<'; - - clang::PrintingPolicy PPol(Result.Context->getLangOpts()); - PPol.TerseOutput = true; - - for (unsigned I = 0; I < TArgs.size(); ++I) { - if (I > 0) - OS << ", "; - TArgs.get(I).getAsType().print(OS, PPol); - } - OS << '>'; - - ClassInheritance[ClassName] = TArgsString.str().str(); - } else { - ClassInheritance[ClassName] = DerivedFrom->getName().str(); - } - } - - if (const auto *Templ = ASTClass->getDescribedClassTemplate()) { - if (auto *TParams = Templ->getTemplateParameters()) { - for (const auto &TParam : *TParams) { - CD.TemplateParms.push_back(TParam->getName().str()); - } - } - } - - ClassEntries[ClassName] = CD; - ClassesInClade[CladeName].push_back(ClassName); -} diff --git a/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.h b/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.h deleted file mode 100644 index 5f2b48173f281eac3e4322a011dbd0f58cc80264..0000000000000000000000000000000000000000 --- a/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.h +++ /dev/null @@ -1,53 +0,0 @@ -//===- ASTSrcLocProcessor.h ---------------------------------*- C++ -*-----===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLING_DUMPTOOL_ASTSRCLOCPROCESSOR_H -#define LLVM_CLANG_TOOLING_DUMPTOOL_ASTSRCLOCPROCESSOR_H - -#include "APIData.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "llvm/ADT/StringRef.h" -#include -#include -#include - -namespace clang { - -class CompilerInstance; - -namespace tooling { - -class ASTSrcLocProcessor : public ast_matchers::MatchFinder::MatchCallback { -public: - explicit ASTSrcLocProcessor(StringRef JsonPath); - - std::unique_ptr createASTConsumer(CompilerInstance &Compiler, - StringRef File); - - void generate(); - void generateEmpty(); - -private: - void run(const ast_matchers::MatchFinder::MatchResult &Result) override; - - std::optional getCheckTraversalKind() const override { - return TK_IgnoreUnlessSpelledInSource; - } - - llvm::StringMap ClassInheritance; - llvm::StringMap> ClassesInClade; - llvm::StringMap ClassEntries; - - std::string JsonPath; - std::unique_ptr Finder; -}; - -} // namespace tooling -} // namespace clang - -#endif diff --git a/clang/lib/Tooling/DumpTool/CMakeLists.txt b/clang/lib/Tooling/DumpTool/CMakeLists.txt deleted file mode 100644 index 712985bf7e2b426a1704fdff2e65687196fc4ab1..0000000000000000000000000000000000000000 --- a/clang/lib/Tooling/DumpTool/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ - -add_clang_executable(clang-ast-dump - ASTSrcLocProcessor.cpp - ClangSrcLocDump.cpp -) - -target_link_libraries(clang-ast-dump - PRIVATE - clangAST - clangASTMatchers - clangBasic - clangDriver - clangFrontend - clangSerialization - clangToolingCore -) diff --git a/clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp b/clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp deleted file mode 100644 index 1529bfa75d6d58272597a921b75575a5ca41470a..0000000000000000000000000000000000000000 --- a/clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp +++ /dev/null @@ -1,155 +0,0 @@ -//===- ClangSrcLocDump.cpp ------------------------------------*- 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 -// -//===----------------------------------------------------------------------===// - -#include "clang/Basic/Diagnostic.h" -#include "clang/Driver/Compilation.h" -#include "clang/Driver/Driver.h" -#include "clang/Driver/Job.h" -#include "clang/Driver/Options.h" -#include "clang/Driver/Tool.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/TextDiagnosticPrinter.h" -#include "clang/Lex/PreprocessorOptions.h" -#include "clang/Tooling/Tooling.h" -#include "llvm/Option/ArgList.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/JSON.h" -#include "llvm/TargetParser/Host.h" - -#include "ASTSrcLocProcessor.h" - -using namespace clang::tooling; -using namespace clang; -using namespace llvm; - -static cl::list IncludeDirectories( - "I", cl::desc("Include directories to use while compiling"), - cl::value_desc("directory"), cl::Required, cl::OneOrMore, cl::Prefix); - -static cl::opt - SkipProcessing("skip-processing", - cl::desc("Avoid processing the AST header file"), - cl::Required, cl::value_desc("bool")); - -static cl::opt JsonOutputPath("json-output-path", - cl::desc("json output path"), - cl::Required, - cl::value_desc("path")); - -class ASTSrcLocGenerationAction : public clang::ASTFrontendAction { -public: - ASTSrcLocGenerationAction() : Processor(JsonOutputPath) {} - - void ExecuteAction() override { - clang::ASTFrontendAction::ExecuteAction(); - if (getCompilerInstance().getDiagnostics().getNumErrors() > 0) - Processor.generateEmpty(); - else - Processor.generate(); - } - - std::unique_ptr - CreateASTConsumer(clang::CompilerInstance &Compiler, - llvm::StringRef File) override { - return Processor.createASTConsumer(Compiler, File); - } - -private: - ASTSrcLocProcessor Processor; -}; - -static const char Filename[] = "ASTTU.cpp"; - -int main(int argc, const char **argv) { - - cl::ParseCommandLineOptions(argc, argv); - - if (SkipProcessing) { - std::error_code EC; - llvm::raw_fd_ostream JsonOut(JsonOutputPath, EC, llvm::sys::fs::OF_Text); - if (EC) - return 1; - JsonOut << formatv("{0:2}", llvm::json::Value(llvm::json::Object())); - return 0; - } - - std::vector Args; - Args.push_back("-cc1"); - - llvm::transform(IncludeDirectories, std::back_inserter(Args), - [](const std::string &IncDir) { return "-I" + IncDir; }); - - Args.push_back("-fsyntax-only"); - Args.push_back(Filename); - - std::vector Argv(Args.size(), nullptr); - llvm::transform(Args, Argv.begin(), - [](const std::string &Arg) { return Arg.c_str(); }); - - IntrusiveRefCntPtr DiagOpts = - CreateAndPopulateDiagOpts(Argv); - - // Don't output diagnostics, because common scenarios such as - // cross-compiling fail with diagnostics. This is not fatal, but - // just causes attempts to use the introspection API to return no data. - TextDiagnosticPrinter DiagnosticPrinter(llvm::nulls(), &*DiagOpts); - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(new DiagnosticIDs()), &*DiagOpts, - &DiagnosticPrinter, false); - - auto *OFS = new llvm::vfs::OverlayFileSystem(vfs::getRealFileSystem()); - - auto *MemFS = new llvm::vfs::InMemoryFileSystem(); - OFS->pushOverlay(MemFS); - MemFS->addFile(Filename, 0, - MemoryBuffer::getMemBuffer("#include \"clang/AST/AST.h\"\n")); - - auto Files = llvm::makeIntrusiveRefCnt(FileSystemOptions(), OFS); - - auto Driver = std::make_unique( - "clang", llvm::sys::getDefaultTargetTriple(), Diagnostics, - "ast-api-dump-tool", OFS); - - std::unique_ptr Comp( - Driver->BuildCompilation(llvm::ArrayRef(Argv))); - if (!Comp) - return 1; - - const auto &Jobs = Comp->getJobs(); - if (Jobs.size() != 1 || !isa(*Jobs.begin())) { - SmallString<256> error_msg; - llvm::raw_svector_ostream error_stream(error_msg); - Jobs.Print(error_stream, "; ", true); - return 1; - } - - const auto &Cmd = cast(*Jobs.begin()); - const llvm::opt::ArgStringList &CC1Args = Cmd.getArguments(); - - auto Invocation = std::make_unique(); - CompilerInvocation::CreateFromArgs(*Invocation, CC1Args, Diagnostics); - - CompilerInstance Compiler(std::make_shared()); - Compiler.setInvocation(std::move(Invocation)); - - Compiler.createDiagnostics(&DiagnosticPrinter, false); - if (!Compiler.hasDiagnostics()) - return 1; - - // Suppress "2 errors generated" or similar messages - Compiler.getDiagnosticOpts().ShowCarets = false; - Compiler.createSourceManager(*Files); - Compiler.setFileManager(Files.get()); - - ASTSrcLocGenerationAction ScopedToolAction; - Compiler.ExecuteAction(ScopedToolAction); - - Files->clearStatCache(); - - return 0; -} diff --git a/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py b/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py deleted file mode 100755 index 7671f9691c09610a3cb1c046e13315bbc4a1db52..0000000000000000000000000000000000000000 --- a/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py +++ /dev/null @@ -1,452 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import os -import sys -import json -import filecmp -import shutil -import argparse - - -class Generator(object): - - implementationContent = "" - - RefClades = { - "DeclarationNameInfo", - "NestedNameSpecifierLoc", - "TemplateArgumentLoc", - "TypeLoc", - } - - def __init__(self, templateClasses): - self.templateClasses = templateClasses - - def GeneratePrologue(self): - - self.implementationContent += r""" -/*===- Generated file -------------------------------------------*- C++ -*-===*\ -|* *| -|* Introspection of available AST node SourceLocations *| -|* *| -|* Automatically generated file, do not edit! *| -|* *| -\*===----------------------------------------------------------------------===*/ - -namespace clang { -namespace tooling { - -using LocationAndString = SourceLocationMap::value_type; -using RangeAndString = SourceRangeMap::value_type; - -bool NodeIntrospection::hasIntrospectionSupport() { return true; } - -struct RecursionPopper -{ - RecursionPopper(std::vector &TypeLocRecursionGuard) - : TLRG(TypeLocRecursionGuard) - { - - } - - ~RecursionPopper() - { - TLRG.pop_back(); - } - -private: -std::vector &TLRG; -}; -""" - - def GenerateBaseGetLocationsDeclaration(self, CladeName): - InstanceDecoration = "*" - if CladeName in self.RefClades: - InstanceDecoration = "&" - - self.implementationContent += """ -void GetLocationsImpl(SharedLocationCall const& Prefix, - clang::{0} const {1}Object, SourceLocationMap &Locs, - SourceRangeMap &Rngs, - std::vector &TypeLocRecursionGuard); -""".format( - CladeName, InstanceDecoration - ) - - def GenerateSrcLocMethod(self, ClassName, ClassData, CreateLocalRecursionGuard): - - NormalClassName = ClassName - RecursionGuardParam = ( - "" - if CreateLocalRecursionGuard - else ", std::vector& TypeLocRecursionGuard" - ) - - if "templateParms" in ClassData: - TemplatePreamble = "template (Prefix, "{0}"))); -""".format( - locName - ) - - self.implementationContent += "\n" - - if "sourceRanges" in ClassData: - for rngName in ClassData["sourceRanges"]: - self.implementationContent += """ - Rngs.insert(RangeAndString(Object.{0}(), - llvm::makeIntrusiveRefCnt(Prefix, "{0}"))); -""".format( - rngName - ) - - self.implementationContent += "\n" - - if ( - "typeLocs" in ClassData - or "typeSourceInfos" in ClassData - or "nestedNameLocs" in ClassData - or "declNameInfos" in ClassData - ): - if CreateLocalRecursionGuard: - self.implementationContent += ( - "std::vector TypeLocRecursionGuard;\n" - ) - - self.implementationContent += "\n" - - if "typeLocs" in ClassData: - for typeLoc in ClassData["typeLocs"]: - - self.implementationContent += """ - if (Object.{0}()) {{ - GetLocationsImpl( - llvm::makeIntrusiveRefCnt(Prefix, "{0}"), - Object.{0}(), Locs, Rngs, TypeLocRecursionGuard); - }} - """.format( - typeLoc - ) - - self.implementationContent += "\n" - if "typeSourceInfos" in ClassData: - for tsi in ClassData["typeSourceInfos"]: - self.implementationContent += """ - if (Object.{0}()) {{ - GetLocationsImpl(llvm::makeIntrusiveRefCnt( - llvm::makeIntrusiveRefCnt(Prefix, "{0}", - LocationCall::ReturnsPointer), "getTypeLoc"), - Object.{0}()->getTypeLoc(), Locs, Rngs, TypeLocRecursionGuard); - }} - """.format( - tsi - ) - - self.implementationContent += "\n" - - if "nestedNameLocs" in ClassData: - for NN in ClassData["nestedNameLocs"]: - self.implementationContent += """ - if (Object.{0}()) - GetLocationsImpl( - llvm::makeIntrusiveRefCnt(Prefix, "{0}"), - Object.{0}(), Locs, Rngs, TypeLocRecursionGuard); - """.format( - NN - ) - - if "declNameInfos" in ClassData: - for declName in ClassData["declNameInfos"]: - - self.implementationContent += """ - GetLocationsImpl( - llvm::makeIntrusiveRefCnt(Prefix, "{0}"), - Object.{0}(), Locs, Rngs, TypeLocRecursionGuard); - """.format( - declName - ) - - self.implementationContent += "}\n" - - def GenerateFiles(self, OutputFile): - with open(os.path.join(os.getcwd(), OutputFile), "w") as f: - f.write(self.implementationContent) - - def GenerateBaseGetLocationsFunction( - self, - ASTClassNames, - ClassEntries, - CladeName, - InheritanceMap, - CreateLocalRecursionGuard, - ): - - MethodReturnType = "NodeLocationAccessors" - InstanceDecoration = "*" - if CladeName in self.RefClades: - InstanceDecoration = "&" - - Signature = "GetLocations(clang::{0} const {1}Object)".format( - CladeName, InstanceDecoration - ) - ImplSignature = """ - GetLocationsImpl(SharedLocationCall const& Prefix, - clang::{0} const {1}Object, SourceLocationMap &Locs, - SourceRangeMap &Rngs, - std::vector &TypeLocRecursionGuard) - """.format( - CladeName, InstanceDecoration - ) - - self.implementationContent += "void {0} {{ ".format(ImplSignature) - - if CladeName == "TypeLoc": - self.implementationContent += "if (Object.isNull()) return;" - - self.implementationContent += """ - if (llvm::find(TypeLocRecursionGuard, Object) != TypeLocRecursionGuard.end()) - return; - TypeLocRecursionGuard.push_back(Object); - RecursionPopper RAII(TypeLocRecursionGuard); - """ - - RecursionGuardParam = "" - if not CreateLocalRecursionGuard: - RecursionGuardParam = ", TypeLocRecursionGuard" - - ArgPrefix = "*" - if CladeName in self.RefClades: - ArgPrefix = "" - self.implementationContent += ( - "GetLocations{0}(Prefix, {1}Object, Locs, Rngs {2});".format( - CladeName, ArgPrefix, RecursionGuardParam - ) - ) - - if CladeName == "TypeLoc": - self.implementationContent += """ - if (auto QTL = Object.getAs()) { - auto Dequalified = QTL.getNextTypeLoc(); - return GetLocationsImpl(llvm::makeIntrusiveRefCnt(Prefix, "getNextTypeLoc"), - Dequalified, - Locs, - Rngs, - TypeLocRecursionGuard); - }""" - - for ASTClassName in ASTClassNames: - if ASTClassName in self.templateClasses: - continue - if ASTClassName == CladeName: - continue - if CladeName != "TypeLoc": - self.implementationContent += """ -if (auto Derived = llvm::dyn_cast(Object)) {{ - GetLocations{0}(Prefix, *Derived, Locs, Rngs {1}); -}} -""".format( - ASTClassName, RecursionGuardParam - ) - continue - - self.GenerateBaseTypeLocVisit( - ASTClassName, ClassEntries, RecursionGuardParam, InheritanceMap - ) - - self.implementationContent += "}" - - self.implementationContent += """ -{0} NodeIntrospection::{1} {{ - NodeLocationAccessors Result; - SharedLocationCall Prefix; - std::vector TypeLocRecursionGuard; - - GetLocationsImpl(Prefix, Object, Result.LocationAccessors, - Result.RangeAccessors, TypeLocRecursionGuard); -""".format( - MethodReturnType, Signature - ) - - self.implementationContent += "return Result; }" - - def GenerateBaseTypeLocVisit( - self, ASTClassName, ClassEntries, RecursionGuardParam, InheritanceMap - ): - CallPrefix = "Prefix" - if ASTClassName != "TypeLoc": - CallPrefix = """llvm::makeIntrusiveRefCnt(Prefix, - "getAs", LocationCall::IsCast) - """.format( - ASTClassName - ) - - if ASTClassName in ClassEntries: - - self.implementationContent += """ - if (auto ConcreteTL = Object.getAs()) - GetLocations{1}({2}, ConcreteTL, Locs, Rngs {3}); - """.format( - ASTClassName, ASTClassName, CallPrefix, RecursionGuardParam - ) - - if ASTClassName in InheritanceMap: - for baseTemplate in self.templateClasses: - if baseTemplate in InheritanceMap[ASTClassName]: - self.implementationContent += """ - if (auto ConcreteTL = Object.getAs()) - GetLocations{1}({2}, ConcreteTL, Locs, Rngs {3}); - """.format( - InheritanceMap[ASTClassName], - baseTemplate, - CallPrefix, - RecursionGuardParam, - ) - - def GenerateDynNodeVisitor(self, CladeNames): - MethodReturnType = "NodeLocationAccessors" - - Signature = "GetLocations(clang::DynTypedNode const &Node)" - - self.implementationContent += ( - MethodReturnType + " NodeIntrospection::" + Signature + "{" - ) - - for CladeName in CladeNames: - if CladeName == "DeclarationNameInfo": - continue - self.implementationContent += """ - if (const auto *N = Node.get<{0}>()) - """.format( - CladeName - ) - ArgPrefix = "" - if CladeName in self.RefClades: - ArgPrefix = "*" - self.implementationContent += """ - return GetLocations({0}const_cast<{1} *>(N));""".format( - ArgPrefix, CladeName - ) - - self.implementationContent += "\nreturn {}; }" - - def GenerateEpilogue(self): - - self.implementationContent += """ - } -} -""" - - -def main(): - - parser = argparse.ArgumentParser() - parser.add_argument( - "--json-input-path", help="Read API description from FILE", metavar="FILE" - ) - parser.add_argument( - "--output-file", help="Generate output in FILEPATH", metavar="FILEPATH" - ) - parser.add_argument( - "--use-empty-implementation", - help="Generate empty implementation", - action="store", - type=int, - ) - parser.add_argument( - "--empty-implementation", - help="Copy empty implementation from FILEPATH", - action="store", - metavar="FILEPATH", - ) - - options = parser.parse_args() - - use_empty_implementation = options.use_empty_implementation - - if not use_empty_implementation and not os.path.exists(options.json_input_path): - use_empty_implementation = True - - if not use_empty_implementation: - with open(options.json_input_path) as f: - jsonData = json.load(f) - - if not "classesInClade" in jsonData or not jsonData["classesInClade"]: - use_empty_implementation = True - - if use_empty_implementation: - if not os.path.exists(options.output_file) or not filecmp.cmp( - options.empty_implementation, options.output_file - ): - shutil.copyfile(options.empty_implementation, options.output_file) - sys.exit(0) - - templateClasses = [] - for (ClassName, ClassAccessors) in jsonData["classEntries"].items(): - if "templateParms" in ClassAccessors: - templateClasses.append(ClassName) - - g = Generator(templateClasses) - - g.GeneratePrologue() - - for (CladeName, ClassNameData) in jsonData["classesInClade"].items(): - g.GenerateBaseGetLocationsDeclaration(CladeName) - - def getCladeName(ClassName): - for (CladeName, ClassNameData) in jsonData["classesInClade"].items(): - if ClassName in ClassNameData: - return CladeName - - for (ClassName, ClassAccessors) in jsonData["classEntries"].items(): - cladeName = getCladeName(ClassName) - g.GenerateSrcLocMethod( - ClassName, ClassAccessors, cladeName not in Generator.RefClades - ) - - for (CladeName, ClassNameData) in jsonData["classesInClade"].items(): - g.GenerateBaseGetLocationsFunction( - ClassNameData, - jsonData["classEntries"], - CladeName, - jsonData["classInheritance"], - CladeName not in Generator.RefClades, - ) - - g.GenerateDynNodeVisitor(jsonData["classesInClade"].keys()) - - g.GenerateEpilogue() - - g.GenerateFiles(options.output_file) - - -if __name__ == "__main__": - main() diff --git a/clang/lib/Tooling/EmptyNodeIntrospection.inc.in b/clang/lib/Tooling/EmptyNodeIntrospection.inc.in deleted file mode 100644 index 2071c34cbd04dbce4efce8f4949958fb822896af..0000000000000000000000000000000000000000 --- a/clang/lib/Tooling/EmptyNodeIntrospection.inc.in +++ /dev/null @@ -1,48 +0,0 @@ -//===- EmptyNodeIntrospection.inc.in --------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -namespace clang { -namespace tooling { -bool NodeIntrospection::hasIntrospectionSupport() { return false; } - -NodeLocationAccessors NodeIntrospection::GetLocations(clang::Stmt const *) { - return {}; -} -NodeLocationAccessors NodeIntrospection::GetLocations(clang::Decl const *) { - return {}; -} -NodeLocationAccessors NodeIntrospection::GetLocations( - clang::CXXCtorInitializer const *) { - return {}; -} -NodeLocationAccessors NodeIntrospection::GetLocations( - clang::NestedNameSpecifierLoc const&) { - return {}; -} -NodeLocationAccessors NodeIntrospection::GetLocations( - clang::TemplateArgumentLoc const&) { - return {}; -} -NodeLocationAccessors NodeIntrospection::GetLocations( - clang::CXXBaseSpecifier const*) { - return {}; -} -NodeLocationAccessors NodeIntrospection::GetLocations( - clang::TypeLoc const&) { - return {}; -} -NodeLocationAccessors NodeIntrospection::GetLocations( - clang::DeclarationNameInfo const&) { - return {}; -} -NodeLocationAccessors -NodeIntrospection::GetLocations(clang::DynTypedNode const &) { - return {}; -} -} // namespace tooling -} // namespace clang diff --git a/clang/lib/Tooling/NodeIntrospection.cpp b/clang/lib/Tooling/NodeIntrospection.cpp deleted file mode 100644 index f01bb1cb9c3cab58a1bac0a88f72a57b4e696b6c..0000000000000000000000000000000000000000 --- a/clang/lib/Tooling/NodeIntrospection.cpp +++ /dev/null @@ -1,88 +0,0 @@ -//===- NodeIntrospection.h -----------------------------------*- C++ -*----===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the implementation of the NodeIntrospection. -// -//===----------------------------------------------------------------------===// - -#include "clang/Tooling/NodeIntrospection.h" - -#include "clang/AST/AST.h" -#include "llvm/Support/raw_ostream.h" - -namespace clang { - -namespace tooling { - -void LocationCallFormatterCpp::print(const LocationCall &Call, - llvm::raw_ostream &OS) { - if (const LocationCall *On = Call.on()) { - print(*On, OS); - if (On->returnsPointer()) - OS << "->"; - else - OS << '.'; - } - - OS << Call.name() << "()"; -} - -std::string LocationCallFormatterCpp::format(const LocationCall &Call) { - std::string Result; - llvm::raw_string_ostream OS(Result); - print(Call, OS); - OS.flush(); - return Result; -} - -namespace internal { - -static bool locationCallLessThan(const LocationCall *LHS, - const LocationCall *RHS) { - if (!LHS && !RHS) - return false; - if (LHS && !RHS) - return true; - if (!LHS && RHS) - return false; - auto compareResult = LHS->name().compare(RHS->name()); - if (compareResult < 0) - return true; - if (compareResult > 0) - return false; - return locationCallLessThan(LHS->on(), RHS->on()); -} - -bool RangeLessThan::operator()( - std::pair const &LHS, - std::pair const &RHS) const { - if (LHS.first.getBegin() < RHS.first.getBegin()) - return true; - else if (LHS.first.getBegin() != RHS.first.getBegin()) - return false; - - if (LHS.first.getEnd() < RHS.first.getEnd()) - return true; - else if (LHS.first.getEnd() != RHS.first.getEnd()) - return false; - - return locationCallLessThan(LHS.second.get(), RHS.second.get()); -} -bool RangeLessThan::operator()( - std::pair const &LHS, - std::pair const &RHS) const { - if (LHS.first == RHS.first) - return locationCallLessThan(LHS.second.get(), RHS.second.get()); - return LHS.first < RHS.first; -} -} // namespace internal - -} // namespace tooling -} // namespace clang - -#include "clang/Tooling/NodeIntrospection.inc" diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp index afdfd25527e4a187bdd71aec96e7468ed618303b..fbe76aba73c90e26859a1a26262171ce5d9c7132 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -644,24 +644,23 @@ static_assert(__builtin_os_log_format_buffer_size("%{mask.xyz}s", "abc") != 0, " /// Some tests are missing since we run this for multiple targets, /// some of which do not support _BitInt. #ifndef __AVR__ -namespace convertvector { - typedef _BitInt(128) BitInt128; - - typedef double vector4double __attribute__((__vector_size__(32))); - typedef float vector4float __attribute__((__vector_size__(16))); - typedef long long vector4long __attribute__((__vector_size__(32))); - typedef int vector4int __attribute__((__vector_size__(16))); - typedef short vector4short __attribute__((__vector_size__(8))); - typedef char vector4char __attribute__((__vector_size__(4))); - typedef BitInt128 vector4BitInt128 __attribute__((__vector_size__(64))); - typedef double vector8double __attribute__((__vector_size__(64))); - typedef float vector8float __attribute__((__vector_size__(32))); - typedef long long vector8long __attribute__((__vector_size__(64))); - typedef int vector8int __attribute__((__vector_size__(32))); - typedef short vector8short __attribute__((__vector_size__(16))); - typedef char vector8char __attribute__((__vector_size__(8))); - typedef BitInt128 vector8BitInt128 __attribute__((__vector_size__(128))); +typedef _BitInt(128) BitInt128; +typedef double vector4double __attribute__((__vector_size__(32))); +typedef float vector4float __attribute__((__vector_size__(16))); +typedef long long vector4long __attribute__((__vector_size__(32))); +typedef int vector4int __attribute__((__vector_size__(16))); +typedef short vector4short __attribute__((__vector_size__(8))); +typedef char vector4char __attribute__((__vector_size__(4))); +typedef BitInt128 vector4BitInt128 __attribute__((__vector_size__(64))); +typedef double vector8double __attribute__((__vector_size__(64))); +typedef float vector8float __attribute__((__vector_size__(32))); +typedef long long vector8long __attribute__((__vector_size__(64))); +typedef int vector8int __attribute__((__vector_size__(32))); +typedef short vector8short __attribute__((__vector_size__(16))); +typedef char vector8char __attribute__((__vector_size__(8))); +typedef BitInt128 vector8BitInt128 __attribute__((__vector_size__(128))); +namespace convertvector { constexpr vector4double from_vector4double_to_vector4double_var = __builtin_convertvector((vector4double){0, 1, 2, 3}, vector4double); constexpr vector4float from_vector4double_to_vector4float_var = @@ -873,4 +872,37 @@ namespace convertvector { static_assert(from_vector8BitInt128_to_vector8BitInt128_var[3] == 3, ""); // ref-error {{not an integral constant expression}} static_assert(from_vector8BitInt128_to_vector8BitInt128_var[4] == 4, ""); // ref-error {{not an integral constant expression}} } + +namespace shufflevector { + constexpr vector4char vector4charConst1 = {0, 1, 2, 3}; + constexpr vector4char vector4charConst2 = {4, 5, 6, 7}; + constexpr vector8char vector8intConst = {8, 9, 10, 11, 12, 13, 14, 15}; + constexpr vector4char vectorShuffle1 = + __builtin_shufflevector(vector4charConst1, vector4charConst2, 0, 1, 2, 3); + constexpr vector4char vectorShuffle2 = + __builtin_shufflevector(vector4charConst1, vector4charConst2, 4, 5, 6, 7); + constexpr vector4char vectorShuffle3 = + __builtin_shufflevector(vector4charConst1, vector4charConst2, 0, 2, 4, 6); + constexpr vector8char vectorShuffle4 = __builtin_shufflevector( + vector8intConst, vector8intConst, 0, 2, 4, 6, 8, 10, 12, 14); + constexpr vector4char vectorShuffle5 = + __builtin_shufflevector(vector8intConst, vector8intConst, 0, 2, 4, 6); + constexpr vector8char vectorShuffle6 = __builtin_shufflevector( + vector4charConst1, vector4charConst2, 0, 2, 4, 6, 1, 3, 5, 7); + + static_assert(vectorShuffle6[0] == 0, "");// ref-error {{not an integral constant expression}} + static_assert(vectorShuffle6[1] == 2, "");// ref-error {{not an integral constant expression}} + static_assert(vectorShuffle6[2] == 4, "");// ref-error {{not an integral constant expression}} + static_assert(vectorShuffle6[3] == 6, "");// ref-error {{not an integral constant expression}} + static_assert(vectorShuffle6[4] == 1, "");// ref-error {{not an integral constant expression}} + static_assert(vectorShuffle6[5] == 3, "");// ref-error {{not an integral constant expression}} + static_assert(vectorShuffle6[6] == 5, "");// ref-error {{not an integral constant expression}} + static_assert(vectorShuffle6[7] == 7, "");// ref-error {{not an integral constant expression}} + + constexpr vector4char vectorShuffleFail1 = __builtin_shufflevector( // both-error {{must be initialized by a constant expression}}\ + // ref-error {{index for __builtin_shufflevector not within the bounds of the input vectors; index of -1 found at position 0 not permitted in a constexpr context.}} + vector4charConst1, + vector4charConst2, -1, -1, -1, -1); +} + #endif diff --git a/clang/test/AST/ast-dump-ctad-alias.cpp b/clang/test/AST/ast-dump-ctad-alias.cpp index 423c3454ccb73e9c3c5a347ba697daa1aa012495..9382558393e4c0eeae744c98a1d9433cf4f98d27 100644 --- a/clang/test/AST/ast-dump-ctad-alias.cpp +++ b/clang/test/AST/ast-dump-ctad-alias.cpp @@ -24,17 +24,47 @@ Out2::AInner t(1.0); // Verify that the require-clause of alias deduction guide is transformed correctly: // - Occurrence T should be replaced with `int`; // - Occurrence V should be replaced with the Y with depth 1 +// - Depth of occurrence Y in the __is_deducible constraint should be 1 // // CHECK: | `-FunctionTemplateDecl {{.*}} // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 Y -// CHECK-NEXT: | |-UnresolvedLookupExpr {{.*}} '' lvalue (no ADL) = 'Concept' -// CHECK-NEXT: | | |-TemplateArgument type 'int' -// CHECK-NEXT: | | | `-BuiltinType {{.*}} 'int' -// CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-1-0' -// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0 +// CHECK-NEXT: | |-BinaryOperator {{.*}} '' '&&' +// CHECK-NEXT: | | |-UnresolvedLookupExpr {{.*}} '' lvalue (no ADL) = 'Concept' +// CHECK-NEXT: | | | |-TemplateArgument type 'int' +// CHECK-NEXT: | | | | `-BuiltinType {{.*}} 'int' +// CHECK-NEXT: | | | `-TemplateArgument type 'type-parameter-1-0' +// CHECK-NEXT: | | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0 +// CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_deducible +// CHECK-NEXT: | | |-DeducedTemplateSpecializationType {{.*}} 'AInner' dependent +// CHECK-NEXT: | | `-ElaboratedType {{.*}} 'Inner' sugar dependent +// CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner' dependent Inner +// CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-1-0' +// CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'type-parameter-1-0' +// CHECK-NEXT: | | |-FunctionTemplate {{.*}} '' +// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0 // CHECK-NEXT: | |-CXXDeductionGuideDecl {{.*}} 'auto (type-parameter-0-0) -> Inner' // CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0' // CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} used 'auto (double) -> Inner' implicit_instantiation // CHECK-NEXT: | |-TemplateArgument type 'double' // CHECK-NEXT: | | `-BuiltinType {{.*}} 'double' // CHECK-NEXT: | `-ParmVarDecl {{.*}} 'double' + +template +struct Foo { + Foo(T1...); +}; + +template +using AFoo = Foo; +AFoo a(1, 2); +// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (type-parameter-0-0...) -> Foo' +// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0...' pack +// CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (int, int) -> Foo' implicit_instantiation + +template +using BFoo = Foo; +BFoo b2(1.0, 2.0); +// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (type-parameter-0-0, type-parameter-0-0) -> Foo' +// CHECK-NEXT: | | |-ParmVarDecl {{.*}} 'type-parameter-0-0' +// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0' +// CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (double, double) -> Foo' implicit_instantiation diff --git a/clang/test/AST/ast-dump-default-init-json.cpp b/clang/test/AST/ast-dump-default-init-json.cpp index f4949a9c9eedf4f5ac024ac9660c11f57a39b89d..1058b4e3ea4d93d9cbd6003034568a0d038ceb5f 100644 --- a/clang/test/AST/ast-dump-default-init-json.cpp +++ b/clang/test/AST/ast-dump-default-init-json.cpp @@ -789,10 +789,10 @@ void test() { // CHECK-NEXT: "valueCategory": "lvalue", // CHECK-NEXT: "extendingDecl": { // CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "VarDecl", -// CHECK-NEXT: "name": "b", +// CHECK-NEXT: "kind": "FieldDecl", +// CHECK-NEXT: "name": "a", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "B" +// CHECK-NEXT: "qualType": "const A &" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "storageDuration": "automatic", diff --git a/clang/test/AST/ast-dump-default-init.cpp b/clang/test/AST/ast-dump-default-init.cpp index 26864fbf15424dc6af8815e3cdc02d836f111b51..15b29f04bf21bf6700096a2f1f03577e9d95f312 100644 --- a/clang/test/AST/ast-dump-default-init.cpp +++ b/clang/test/AST/ast-dump-default-init.cpp @@ -13,7 +13,7 @@ void test() { } // 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 Var 0x{{[^ ]*}} 'b' 'B' +// 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' diff --git a/clang/test/AST/ast-dump-expr-json.cpp b/clang/test/AST/ast-dump-expr-json.cpp index 0fb07b0b434cc3861782e0119dae2d0d2e5dbade..4b7365e554cb7c8af20613e107380a53f322b6a6 100644 --- a/clang/test/AST/ast-dump-expr-json.cpp +++ b/clang/test/AST/ast-dump-expr-json.cpp @@ -4261,9 +4261,9 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "" +// CHECK-NEXT: "qualType": "V" // CHECK-NEXT: }, -// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "valueCategory": "lvalue", // CHECK-NEXT: "isPostfix": false, // CHECK-NEXT: "opcode": "*", // CHECK-NEXT: "canOverflow": false, diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp index 69e65e22d61d0d0d2198f360388f81db030ff94f..604868103dab8b8fdbec5d373ab8efb7fe37ba80 100644 --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -282,7 +282,7 @@ void PrimaryExpressions(Ts... a) { // CHECK-NEXT: CompoundStmt // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} col:8 implicit 'V' // CHECK-NEXT: ParenListExpr 0x{{[^ ]*}} 'NULL TYPE' - // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} '' prefix '*' cannot overflow + // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} 'V' lvalue prefix '*' cannot overflow // CHECK-NEXT: CXXThisExpr 0x{{[^ ]*}} 'V *' this } }; @@ -583,3 +583,10 @@ void NonADLCall3() { f(x); } } // namespace test_adl_call_three + +namespace GH35300 { +struct Sock {}; +void leakNewFn() { new struct Sock; } +// CHECK: CXXNewExpr {{.*}} 'struct Sock *' +} + diff --git a/clang/test/AST/ast-dump-lambda.cpp b/clang/test/AST/ast-dump-lambda.cpp index ef8789cd97d3e79559ebc3807808c74616939f05..a4d3fe4fbda57c6f91a767d3dab9642c74fab122 100644 --- a/clang/test/AST/ast-dump-lambda.cpp +++ b/clang/test/AST/ast-dump-lambda.cpp @@ -81,7 +81,7 @@ template void test(Ts... a) { // CHECK-NEXT: | | | `-CompoundStmt {{.*}} // CHECK-NEXT: | | `-FieldDecl {{.*}} col:8{{( imported)?}} implicit 'V' // CHECK-NEXT: | |-ParenListExpr {{.*}} 'NULL TYPE' -// CHECK-NEXT: | | `-UnaryOperator {{.*}} '' prefix '*' cannot overflow +// CHECK-NEXT: | | `-UnaryOperator {{.*}} 'V' lvalue prefix '*' cannot overflow // CHECK-NEXT: | | `-CXXThisExpr {{.*}} 'V *' this // CHECK-NEXT: | `-CompoundStmt {{.*}} // CHECK-NEXT: |-DeclStmt {{.*}} diff --git a/clang/test/AST/const-fpfeatures.c b/clang/test/AST/const-fpfeatures.c index 083350fdc8ce6a87db0dd3d7e8056a8caa180fc0..8dc3221b0638a355e07265175a2c2d55c626ba52 100644 --- a/clang/test/AST/const-fpfeatures.c +++ b/clang/test/AST/const-fpfeatures.c @@ -19,6 +19,9 @@ float FI1u = 0xFFFFFFFFU; float _Complex C1u = C0; // CHECK: @C1u = {{.*}} { float, float } { float 0x3FF0000020000000, float 0x3FF0000020000000 } +float FLu = 0.1F; +// CHECK: @FLu = {{.*}} float 0x3FB99999A0000000 + #pragma STDC FENV_ROUND FE_DOWNWARD @@ -35,3 +38,6 @@ float FI1d = 0xFFFFFFFFU; float _Complex C1d = C0; // CHECK: @C1d = {{.*}} { float, float } { float 1.000000e+00, float 1.000000e+00 } + +float FLd = 0.1F; +// CHECK: @FLd = {{.*}} float 0x3FB9999980000000 diff --git a/clang/test/AST/const-fpfeatures.cpp b/clang/test/AST/const-fpfeatures.cpp index 95eb613df7f07176af70642d4b05c5a0c87eb239..5e903c8c0e8745382925d71c3613d8f4302b856a 100644 --- a/clang/test/AST/const-fpfeatures.cpp +++ b/clang/test/AST/const-fpfeatures.cpp @@ -79,3 +79,108 @@ float V7 = []() -> float { 0x0.000001p0F); }(); // CHECK: @V7 = {{.*}} float 1.000000e+00 + +#pragma STDC FENV_ROUND FE_DYNAMIC + +template struct L { + constexpr L() : value(V) {} + float value; +}; + +#pragma STDC FENV_ROUND FE_DOWNWARD +L<0.1F> val_d; +// CHECK: @val_d = {{.*}} { float 0x3FB9999980000000 } + +#pragma STDC FENV_ROUND FE_UPWARD +L<0.1F> val_u; +// CHECK: @val_u = {{.*}} { float 0x3FB99999A0000000 } + + +// Check literals in macros. + +#pragma STDC FENV_ROUND FE_DOWNWARD +#define CONSTANT_0_1 0.1F + +#pragma STDC FENV_ROUND FE_UPWARD +float C1_ru = CONSTANT_0_1; +// CHECK: @C1_ru = {{.*}} float 0x3FB99999A0000000 + +#pragma STDC FENV_ROUND FE_DOWNWARD +float C1_rd = CONSTANT_0_1; +// CHECK: @C1_rd = {{.*}} float 0x3FB9999980000000 + +#pragma STDC FENV_ROUND FE_DOWNWARD +#define PRAGMA(x) _Pragma(#x) +#define CONSTANT_0_1_RM(v, rm) ([](){ PRAGMA(STDC FENV_ROUND rm); return v; }()) + +#pragma STDC FENV_ROUND FE_UPWARD +float C2_rd = CONSTANT_0_1_RM(0.1F, FE_DOWNWARD); +float C2_ru = CONSTANT_0_1_RM(0.1F, FE_UPWARD); +// CHECK: @C2_rd = {{.*}} float 0x3FB9999980000000 +// CHECK: @C2_ru = {{.*}} float 0x3FB99999A0000000 + +#pragma STDC FENV_ROUND FE_DOWNWARD +float C3_rd = CONSTANT_0_1_RM(0.1F, FE_DOWNWARD); +float C3_ru = CONSTANT_0_1_RM(0.1F, FE_UPWARD); +// CHECK: @C3_rd = {{.*}} float 0x3FB9999980000000 +// CHECK: @C3_ru = {{.*}} float 0x3FB99999A0000000 + +// Check literals in template instantiations. + +#pragma STDC FENV_ROUND FE_DYNAMIC + +template +constexpr T foo() { + return C; +} + +#pragma STDC FENV_ROUND FE_DOWNWARD +float var_d = foo(); +// CHECK: @var_d = {{.*}} float 0x3FB9999980000000 + +#pragma STDC FENV_ROUND FE_UPWARD +float var_u = foo(); +// CHECK: @var_u = {{.*}} float 0x3FB99999A0000000 + +#pragma STDC FENV_ROUND FE_DYNAMIC + +template void foo2() { + T Val = f; +} + +void func_01() { + #pragma STDC FENV_ROUND FE_DOWNWARD + foo2(); +} + +void func_02() { + #pragma STDC FENV_ROUND FE_UPWARD + foo2(); +} + +// CHECK-LABEL: define {{.*}} void @_Z4foo2IfTnT_Lf3dccccccEEvv() +// CHECK: store float 0x3FB9999980000000, ptr + +// CHECK-LABEL: define {{.*}} void @_Z4foo2IfTnT_Lf3dcccccdEEvv() +// CHECK: store float 0x3FB99999A0000000, ptr + + +#pragma STDC FENV_ROUND FE_DOWNWARD +template +float tfunc_01() { + return 0.1F; // Must be 0x3FB9999980000000 in all instantiations. +} +template float tfunc_01<0>(); +// CHECK-LABEL: define {{.*}} float @_Z8tfunc_01ILi0EEfv() +// CHECK: ret float 0x3FB9999980000000 + +#pragma STDC FENV_ROUND FE_UPWARD +template float tfunc_01<1>(); +// CHECK-LABEL: define {{.*}} float @_Z8tfunc_01ILi1EEfv() +// CHECK: ret float 0x3FB9999980000000 + +template<> float tfunc_01<2>() { + return 0.1F; +} +// CHECK-LABEL: define {{.*}} float @_Z8tfunc_01ILi2EEfv() +// CHECK: ret float 0x3FB99999A0000000 diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp index ed37671df3d3ebe05bd5c87f11f292543d7278ca..96986631726fe3442cb0f5fb75fd1dcb8eb616a6 100644 --- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp @@ -159,10 +159,13 @@ private: StorageType m_storage { 0 }; }; +int atoi(const char* str); + class Number { public: Number(int v) : v(v) { } Number(double); + Number(const char* str) : v(atoi(str)) { } Number operator+(const Number&); Number& operator++() { ++v; return *this; } Number operator++(int) { Number returnValue(v); ++v; return returnValue; } @@ -173,9 +176,16 @@ private: int v; }; +class DerivedNumber : public Number { +public: + DerivedNumber(char c) : Number(c - '0') { } + DerivedNumber(const char* str) : Number(atoi(str)) { } +}; + class ComplexNumber { public: ComplexNumber() : realPart(0), complexPart(0) { } + ComplexNumber(int real, const char* str) : realPart(real), complexPart(str) { } ComplexNumber(const ComplexNumber&); ComplexNumber& operator++() { realPart.someMethod(); return *this; } ComplexNumber operator++(int); @@ -311,6 +321,7 @@ public: return; } unsigned trivial60() { return ObjectWithNonTrivialDestructor { 5 }.value(); } + unsigned trivial61() { return DerivedNumber('7').value(); } static RefCounted& singleton() { static RefCounted s_RefCounted; @@ -391,6 +402,9 @@ public: ComplexNumber nonTrivial18() { return +complex; } ComplexNumber* nonTrivial19() { return new ComplexNumber(complex); } unsigned nonTrivial20() { return ObjectWithMutatingDestructor { 7 }.value(); } + unsigned nonTrivial21() { return Number("123").value(); } + unsigned nonTrivial22() { return ComplexNumber(123, "456").real().value(); } + unsigned nonTrivial23() { return DerivedNumber("123").value(); } static unsigned s_v; unsigned v { 0 }; @@ -479,6 +493,7 @@ public: getFieldTrivial().trivial58(); // no-warning getFieldTrivial().trivial59(); // no-warning getFieldTrivial().trivial60(); // no-warning + getFieldTrivial().trivial61(); // no-warning RefCounted::singleton().trivial18(); // no-warning RefCounted::singleton().someFunction(); // no-warning @@ -525,6 +540,12 @@ public: // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} getFieldTrivial().nonTrivial20(); // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} + getFieldTrivial().nonTrivial21(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} + getFieldTrivial().nonTrivial22(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} + getFieldTrivial().nonTrivial23(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} } }; diff --git a/clang/test/Analysis/lifetime-extended-regions.cpp b/clang/test/Analysis/lifetime-extended-regions.cpp index 4458ad294af7cb027165df5624e20eb29db8d472..4e98bd4b0403ebc89ea84fee70424cd18a5db16c 100644 --- a/clang/test/Analysis/lifetime-extended-regions.cpp +++ b/clang/test/Analysis/lifetime-extended-regions.cpp @@ -120,11 +120,10 @@ void aggregateWithReferences() { clang_analyzer_dump(viaReference); // expected-warning-re {{&lifetime_extended_object{RefAggregate, viaReference, S{{[0-9]+}}} }} clang_analyzer_dump(viaReference.rx); // expected-warning-re {{&lifetime_extended_object{int, viaReference, S{{[0-9]+}}} }} clang_analyzer_dump(viaReference.ry); // expected-warning-re {{&lifetime_extended_object{Composite, viaReference, S{{[0-9]+}}} }} - - // FIXME: clang currently support extending lifetime of object bound to reference members of aggregates, - // that are created from default member initializer. But CFG and ExprEngine need to be updated to address this change. - // The following expect warning: {{&lifetime_extended_object{Composite, defaultInitExtended, S{{[0-9]+}}} }} - RefAggregate defaultInitExtended{i}; + + // clang does not currently implement extending lifetime of object bound to reference members of aggregates, + // that are created from default member initializer (see `warn_unsupported_lifetime_extension` from `-Wdangling`) + RefAggregate defaultInitExtended{i}; // clang-bug does not extend `Composite` clang_analyzer_dump(defaultInitExtended.ry); // expected-warning {{Unknown }} } diff --git a/clang/test/C/C2x/n2900_n3011.c b/clang/test/C/C2x/n2900_n3011.c index 4350aa140691b1d5c026b04c78d1b91e31a0f951..82a3b16c8acda134e16e17e87f85c4103d5a533a 100644 --- a/clang/test/C/C2x/n2900_n3011.c +++ b/clang/test/C/C2x/n2900_n3011.c @@ -27,8 +27,14 @@ void test(void) { compat-warning {{use of an empty initializer is incompatible with C standards before C23}} int vla[i] = {}; // compat-warning {{use of an empty initializer is incompatible with C standards before C23}} \ pedantic-warning {{use of an empty initializer is a C23 extension}} + // C99 6.5.2.5 Compound literals constraint 1: The type name shall specify an + // object type or an array of unknown size, but not a variable length array + // type. int *compound_literal_vla = (int[i]){}; // compat-warning {{use of an empty initializer is incompatible with C standards before C23}} \ - pedantic-warning {{use of an empty initializer is a C23 extension}} + pedantic-warning {{use of an empty initializer is a C23 extension}}\ + compat-error {{compound literal cannot be of variable-length array type}} \ + pedantic-error {{compound literal cannot be of variable-length array type}}\ + struct T { int i; diff --git a/clang/test/C/C2x/n2900_n3011_2.c b/clang/test/C/C2x/n2900_n3011_2.c index eb15fbf905c86f0bb0f891aae5376f6cf43e575b..ab659d636d155c78dc23add1d374e3aba40cb523 100644 --- a/clang/test/C/C2x/n2900_n3011_2.c +++ b/clang/test/C/C2x/n2900_n3011_2.c @@ -76,22 +76,6 @@ void test_zero_size_vla() { // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr {{.*}} %[[VLA]], i8 0, i64 %[[BYTES_TO_COPY]], i1 false) } -void test_compound_literal_vla() { - int num_elts = 12; - int *compound_literal_vla = (int[num_elts]){}; - // CHECK: define {{.*}} void @test_compound_literal_vla - // CHECK-NEXT: entry: - // CHECK-NEXT: %[[NUM_ELTS_PTR:.+]] = alloca i32 - // CHECK-NEXT: %[[COMP_LIT_VLA:.+]] = alloca ptr - // CHECK-NEXT: %[[COMP_LIT:.+]] = alloca i32 - // CHECK-NEXT: store i32 12, ptr %[[NUM_ELTS_PTR]] - // CHECK-NEXT: %[[NUM_ELTS:.+]] = load i32, ptr %[[NUM_ELTS_PTR]] - // CHECK-NEXT: %[[NUM_ELTS_EXT:.+]] = zext i32 %[[NUM_ELTS]] to i64 - // CHECK-NEXT: %[[BYTES_TO_COPY:.+]] = mul nuw i64 %[[NUM_ELTS_EXT]], 4 - // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr {{.*}} %[[COMP_LIT]], i8 0, i64 %[[BYTES_TO_COPY]], i1 false) - // CHECK-NEXT: store ptr %[[COMP_LIT]], ptr %[[COMP_LIT_VLA]] -} - void test_nested_structs() { struct T t1 = { 1, {} }; struct T t2 = { 1, { 2, {} } }; diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index a28a5f91c47756eb283ce3ff850b2edd091fc6d9..788e93b56bb382999cfd5ff1e68431f97ba920e3 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -154,3 +154,14 @@ namespace { // FIXME: We should diagnose this prior to C++17. const int &r = A::n; } + +#if __cplusplus < 201402L +namespace ImplicitConstexprDef { + struct A { + void f(); // expected-note {{member declaration does not match because it is not const qualified}} + }; + + constexpr void A::f() { } // expected-warning {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const' to avoid a change in behavior}} + // expected-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'ImplicitConstexprDef::A'}} +} +#endif diff --git a/clang/test/CXX/drs/cwg11xx.cpp b/clang/test/CXX/drs/cwg11xx.cpp index 46a0e526be390c5ab6e3df3947eb85897eb3feff..8d187041400a601be5a48f4019b3071343f6c3a8 100644 --- a/clang/test/CXX/drs/cwg11xx.cpp +++ b/clang/test/CXX/drs/cwg11xx.cpp @@ -4,6 +4,21 @@ // 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 cwg1110 { // cwg1110: 3.1 +#if __cplusplus >= 201103L +template +T return_T(); + +struct A; + +template +struct B; + +decltype(return_T())* a; +decltype(return_T>())* b; +#endif +} // namespace cwg1110 + namespace cwg1111 { // cwg1111: 3.2 namespace example1 { template struct set; // #cwg1111-struct-set diff --git a/clang/test/CXX/drs/cwg13xx.cpp b/clang/test/CXX/drs/cwg13xx.cpp index a334b6d01acf51fcfb6e5ada5242b81296c82243..416de7c536b1a467c40ea1570b42a3745e34df96 100644 --- a/clang/test/CXX/drs/cwg13xx.cpp +++ b/clang/test/CXX/drs/cwg13xx.cpp @@ -306,6 +306,18 @@ namespace cwg1330 { // cwg1330: 4 c++11 // cwg1334: sup 1719 +namespace cwg1340 { // cwg1340: 2.9 +struct A; +struct B; + +void f(B* a, A B::* p) { + (*a).*p; + // expected-warning@-1 {{expression result unused}} + a->*p; + // expected-warning@-1 {{expression result unused}} +} +} // namespace cwg1340 + namespace cwg1341 { // cwg1341: sup P0683R1 #if __cplusplus >= 202002L int a; @@ -451,6 +463,25 @@ static_assert(!__is_nothrow_constructible(D4, int), ""); #endif } // namespace cwg1350 +namespace cwg1352 { // cwg1352: 3.0 +struct A { +#if __cplusplus >= 201103L + int a = sizeof(A); +#endif + void f(int b = sizeof(A)); +}; + +template +struct B { +#if __cplusplus >= 201103L + int a = sizeof(B) + sizeof(T); +#endif + void f(int b = sizeof(B) + sizeof(T)); +}; + +template class B; +} // namespace cwg1352 + namespace cwg1358 { // cwg1358: 3.1 #if __cplusplus >= 201103L struct Lit { constexpr operator int() const { return 0; } }; diff --git a/clang/test/CXX/drs/cwg14xx.cpp b/clang/test/CXX/drs/cwg14xx.cpp index 9ff9a68dc13c3059cb452c9cfea5964635277f5f..f01d96ad47f3e3ad6ca3accb4487b10ee55d9a97 100644 --- a/clang/test/CXX/drs/cwg14xx.cpp +++ b/clang/test/CXX/drs/cwg14xx.cpp @@ -86,6 +86,23 @@ struct A { }; } +namespace cwg1458 { // cwg1458: 3.1 +#if __cplusplus >= 201103L +struct A; + +void f() { + constexpr A* a = nullptr; + constexpr int p = &*a; + // expected-error@-1 {{cannot initialize a variable of type 'const int' with an rvalue of type 'A *'}} + constexpr A *p2 = &*a; +} + +struct A { + int operator&(); +}; +#endif +} // namespace cwg1458 + namespace cwg1460 { // cwg1460: 3.5 #if __cplusplus >= 201103L namespace DRExample { diff --git a/clang/test/CXX/drs/cwg16xx.cpp b/clang/test/CXX/drs/cwg16xx.cpp index 82ef871939d2c468efc3837384c8f53db695562d..cf6b45ceabf2cc8f85bea33900fe3d3a1a4375f8 100644 --- a/clang/test/CXX/drs/cwg16xx.cpp +++ b/clang/test/CXX/drs/cwg16xx.cpp @@ -483,6 +483,8 @@ namespace cwg1696 { // cwg1696: 7 const A &a = A(); // #cwg1696-D1-a }; 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@#cwg1696-D1-a {{initializing field 'a' with default member initializer}} struct D2 { const A &a = A(); // #cwg1696-D2-a diff --git a/clang/test/CXX/drs/cwg18xx.cpp b/clang/test/CXX/drs/cwg18xx.cpp index 9eb749153e57a23d0bf5185fe0a9177f65512c25..35615076a6288070c4f0936d2821cf3cdf4363bc 100644 --- a/clang/test/CXX/drs/cwg18xx.cpp +++ b/clang/test/CXX/drs/cwg18xx.cpp @@ -56,7 +56,7 @@ namespace cwg1804 { // cwg1804: 2.7 template struct A { void f1(); - + template void f2(V); @@ -73,7 +73,7 @@ struct A { template struct A { void f1(); - + template void f2(V); @@ -97,7 +97,7 @@ class D { template struct A { void f1(); - + template void f2(V); @@ -206,28 +206,19 @@ namespace cwg1814 { // cwg1814: yes #endif } -namespace cwg1815 { // cwg1815: yes +namespace cwg1815 { // cwg1815: no #if __cplusplus >= 201402L - struct A { int &&r = 0; }; + // FIXME: needs codegen test + struct A { int &&r = 0; }; // #cwg1815-A A a = {}; + // 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}} FIXME + // since-cxx14-note@#cwg1815-A {{initializing field 'r' with default member initializer}} struct B { int &&r = 0; }; // #cwg1815-B // since-cxx14-error@-1 {{reference member 'r' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} // since-cxx14-note@#cwg1815-B {{initializing field 'r' with default member initializer}} // since-cxx14-note@#cwg1815-b {{in implicit default constructor for 'cwg1815::B' first required here}} B b; // #cwg1815-b - -#if __cplusplus >= 201703L - struct C { const int &r = 0; }; - constexpr C c = {}; // OK, since cwg1815 - static_assert(c.r == 0); - - constexpr int f() { - A a = {}; // OK, since cwg1815 - return a.r; - } - static_assert(f() == 0); -#endif #endif } @@ -303,6 +294,32 @@ namespace cwg1822 { // cwg1822: yes #endif } +namespace cwg1824 { // cwg1824: 2.7 +template +struct A { + T t; +}; + +struct S { + A f() { return A(); } +}; +} // namespace cwg1824 + +namespace cwg1832 { // cwg1832: 3.0 +enum E { // #cwg1832-E + a = static_cast(static_cast(0)) + // expected-error@-1 {{'E' is an incomplete type}} + // expected-note@#cwg1832-E {{definition of 'cwg1832::E' is not complete until the closing '}'}} +}; + +#if __cplusplus >= 201103L +enum E2: decltype(static_cast(0), 0) {}; +// expected-error@-1 {{unknown type name 'E2'}} +enum class E3: decltype(static_cast(0), 0) {}; +// expected-error@-1 {{unknown type name 'E3'}} +#endif +} // namespace cwg1832 + namespace cwg1837 { // cwg1837: 3.3 #if __cplusplus >= 201103L template diff --git a/clang/test/CXX/drs/cwg23xx.cpp b/clang/test/CXX/drs/cwg23xx.cpp index db5b7c3cd3c9a2b04ef0f7098aa1132494fd0b5b..ae5ec3b878f59ffd85b3257e0c2b02816c56b29f 100644 --- a/clang/test/CXX/drs/cwg23xx.cpp +++ b/clang/test/CXX/drs/cwg23xx.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -std=c++98 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++11 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++14 %s -verify=expected,since-cxx11,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-14,since-cxx11,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s // RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s // RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s @@ -47,6 +47,50 @@ void g() { } // namespace cwg2303 #endif +namespace cwg2304 { // cwg2304: 2.8 +template void foo(T, int); +template void foo(T&, ...); +struct Q; // #cwg2304-Q +void fn1(Q &data_vectors) { + foo(data_vectors, 0); + // expected-error@-1 {{argument type 'cwg2304::Q' is incomplete}} + // expected-note@#cwg2304-Q {{forward declaration of 'cwg2304::Q'}} +} +} // namespace cwg2304 + +namespace cwg2310 { // cwg2310: partial +#if __cplusplus >= 201103L +template +struct check_derived_from { + static A a; + // FIXME: all 3 examples should be rejected in all language modes. + // FIXME: we should test this in 98 mode. + // FIXME: we accept this when MSVC triple is used + static constexpr B *p = &a; +#if !defined(_WIN32) || defined(__MINGW32__) + // cxx11-14-error@-2 {{cannot initialize a variable of type 'cwg2310::X *const' with an rvalue of type 'cwg2310::Z *'}} + // cxx11-14-note@#cwg2310-X {{in instantiation of template class 'cwg2310::check_derived_from' requested here}} + // cxx11-14-error@-4 {{cannot initialize a variable of type 'cwg2310::Y *const' with an rvalue of type 'cwg2310::Z *'}} + // cxx11-14-note@#cwg2310-Y {{in instantiation of template class 'cwg2310::check_derived_from' requested here}} +#endif +}; + +struct W {}; +struct X {}; +struct Y {}; +struct Z : W, + X, check_derived_from, // #cwg2310-X + check_derived_from, Y // #cwg2310-Y +{ + // FIXME: It was properly rejected before, but we're crashing since Clang 11 in C++11 and C++14 modes. + // See https://github.com/llvm/llvm-project/issues/59920 +#if __cplusplus >= 201703L + check_derived_from cdf; +#endif +}; +#endif +} // namespace cwg2310 + // cwg2331: na // cwg2335 is in cwg2335.cxx diff --git a/clang/test/CXX/drs/cwg24xx.cpp b/clang/test/CXX/drs/cwg24xx.cpp index 9f876cd8708347077f297edd6c261c8583b70698..4c7b1506e86eae81da9cf0f83dd1038286efae22 100644 --- a/clang/test/CXX/drs/cwg24xx.cpp +++ b/clang/test/CXX/drs/cwg24xx.cpp @@ -45,6 +45,54 @@ void fallthrough(int n) { #endif } +namespace cwg2428 { // cwg2428: 19 +#if __cplusplus >= 202002L +template +concept C [[deprecated]] = true; // #cwg2428-C + +template +[[deprecated]] concept C2 = true; +// expected-error@-1 {{expected unqualified-id}} + +template +concept C3 = C; +// expected-warning@-1 {{'C' is deprecated}} +// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}} + +template +// expected-warning@-1 {{'C' is deprecated}} +// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}} +requires C +// expected-warning@-1 {{'C' is deprecated}} +// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}} +void f() { + bool b = C; + // expected-warning@-1 {{'C' is deprecated}} + // expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}} +}; + +void g(C auto a) {}; +// expected-warning@-1 {{'C' is deprecated}} +// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}} + +template +auto h() -> C auto { +// expected-warning@-1 {{'C' is deprecated}} +// expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}} + C auto foo = T(); + // expected-warning@-1 {{'C' is deprecated}} + // expected-note@#cwg2428-C {{'C' has been explicitly marked deprecated here}} + return foo; +} +#endif +} // namespace cwg2428 + +namespace cwg2430 { // cwg2430: 2.7 +struct S { + S f(S s) { return s; } +}; +} // namespace cwg2430 + namespace cwg2450 { // cwg2450: 18 #if __cplusplus >= 202302L struct S {int a;}; diff --git a/clang/test/CXX/drs/cwg25xx.cpp b/clang/test/CXX/drs/cwg25xx.cpp index 8bca58f44944f71fd2c42f487970cb9ecd9367ef..0934f0cc19c6a9e4dd06039baf84a4be67a639b9 100644 --- a/clang/test/CXX/drs/cwg25xx.cpp +++ b/clang/test/CXX/drs/cwg25xx.cpp @@ -6,12 +6,21 @@ // RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx20,since-cxx23 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx20,since-cxx23 -fexceptions -fcxx-exceptions -pedantic-errors -#if __cplusplus == 199711L -// expected-no-diagnostics -#endif +namespace std { +struct type_info{}; +} // namespace std // cwg2504 is in cwg2504.cpp +namespace cwg2512 { // cwg2512: 2.7 +struct A; // #cwg2512-A +void foo(A* p) { + typeid(*p); + // expected-error@-1 {{'typeid' of incomplete type 'A'}} + // expected-note@#cwg2512-A {{forward declaration of 'cwg2512::A'}} +} +} // namespace cwg2512 + namespace cwg2516 { // cwg2516: 3.0 // NB: reusing 1482 test #if __cplusplus >= 201103L diff --git a/clang/test/CXX/drs/cwg2630.cpp b/clang/test/CXX/drs/cwg2630.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f50dc4f7458c52ff0f14a1b75d09d2b887450ae --- /dev/null +++ b/clang/test/CXX/drs/cwg2630.cpp @@ -0,0 +1,23 @@ +// RUN: split-file --leading-lines %s %t +// RUN: %clang_cc1 -std=c++20 -verify -emit-module-interface %t/module.cppm -o %t/module.pcm +// RUN: %clang_cc1 -std=c++20 -verify -fmodule-file=A=%t/module.pcm %t/main.cpp +// RUN: %clang_cc1 -std=c++23 -verify -emit-module-interface %t/module.cppm -o %t/module.pcm +// RUN: %clang_cc1 -std=c++23 -verify -fmodule-file=A=%t/module.pcm %t/main.cpp +// RUN: %clang_cc1 -std=c++2c -verify -emit-module-interface %t/module.cppm -o %t/module.pcm +// RUN: %clang_cc1 -std=c++2c -verify -fmodule-file=A=%t/module.pcm %t/main.cpp + +//--- module.cppm +// expected-no-diagnostics +export module A; + +namespace cwg2630 { +export class X {}; +} // namespace cwg2630 + +//--- main.cpp +// expected-no-diagnostics +import A; + +namespace cwg2630 { // cwg2630: 9 +X x; +} // namespace cwg2630 diff --git a/clang/test/CXX/drs/cwg26xx.cpp b/clang/test/CXX/drs/cwg26xx.cpp index f7a05b9827a235fafb0d13b9a6ddb362245c5355..d3c5b5bb7b6b9d7e4b3596c1a0dcf0ce9d28b58f 100644 --- a/clang/test/CXX/drs/cwg26xx.cpp +++ b/clang/test/CXX/drs/cwg26xx.cpp @@ -49,6 +49,8 @@ void f() { #endif } +// cwg2630 is in cwg2630.cpp + namespace cwg2631 { // cwg2631: 16 #if __cplusplus >= 202002L constexpr int g(); diff --git a/clang/test/CXX/drs/cwg27xx.cpp b/clang/test/CXX/drs/cwg27xx.cpp index 0434427d6c92a3d26be3ae61190bd1034d1baa85..53ddd566b7dbf9326a56fb00634385573399fda9 100644 --- a/clang/test/CXX/drs/cwg27xx.cpp +++ b/clang/test/CXX/drs/cwg27xx.cpp @@ -6,9 +6,17 @@ // RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -verify=expected,since-cxx23 %s // RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++2c -verify=expected,since-cxx23,since-cxx26 %s -#if __cplusplus <= 202002L -// expected-no-diagnostics -#endif +namespace cwg2718 { // cwg2718: 2.7 +struct B {}; +struct D; + +void f(B b) { + static_cast(b); + // expected-error@-1 {{non-const lvalue reference to type 'D' cannot bind to a value of unrelated type 'B'}} +} + +struct D : B {}; +} // namespace cwg2718 namespace cwg2759 { // cwg2759: 19 #if __cplusplus >= 201103L diff --git a/clang/test/CXX/drs/cwg28xx.cpp b/clang/test/CXX/drs/cwg28xx.cpp index be35d366bdd614cdd7db7224cfda721ffce6b9a0..696cd1b9c84e77417d7fce7dd602dfbaa0e46660 100644 --- a/clang/test/CXX/drs/cwg28xx.cpp +++ b/clang/test/CXX/drs/cwg28xx.cpp @@ -6,10 +6,6 @@ // RUN: %clang_cc1 -std=c++23 -verify=expected,since-cxx20,since-cxx23 %s // RUN: %clang_cc1 -std=c++2c -verify=expected,since-cxx20,since-cxx23,since-cxx26 %s -#if __cplusplus < 202002L -// expected-no-diagnostics -#endif - namespace cwg2819 { // cwg2819: 19 tentatively ready 2023-12-01 #if __cpp_constexpr >= 202306L constexpr void* p = nullptr; @@ -67,6 +63,30 @@ void B::g() requires true; } // namespace cwg2847 +namespace cwg2857 { // cwg2857: no +struct A {}; +template +struct D; +namespace N { + struct B {}; + void adl_only(A*, D*); // #cwg2857-adl_only +} + +void f(A* a, D* d) { + adl_only(a, d); + // expected-error@-1 {{use of undeclared identifier 'adl_only'; did you mean 'N::adl_only'?}} + // expected-note@#cwg2857-adl_only {{'N::adl_only' declared here}} +} + +#if __cplusplus >= 201103L +template +struct D : N::B { + // FIXME: ADL shouldn't associate it's base B and N since D is not complete here + decltype(adl_only((A*) nullptr, (D*) nullptr)) f; +}; +#endif +} // namespace cwg2857 + namespace cwg2858 { // cwg2858: 19 tentatively ready 2024-04-05 #if __cplusplus > 202302L diff --git a/clang/test/CXX/drs/cwg9xx.cpp b/clang/test/CXX/drs/cwg9xx.cpp index 8ecb149c355f6c1eac4c6a9cff7d2a5dbc1951a8..2700b0f5662a2c79e199c1218658f8a68aae74be 100644 --- a/clang/test/CXX/drs/cwg9xx.cpp +++ b/clang/test/CXX/drs/cwg9xx.cpp @@ -14,6 +14,13 @@ namespace std { }; } +namespace cwg930 { // cwg930: 2.7 +#if __cplusplus >= 201103L +static_assert(alignof(int[]) == alignof(int), ""); +static_assert(alignof(int[][2]) == alignof(int[2]), ""); +#endif +} // namespace cwg930 + namespace cwg948 { // cwg948: 3.7 #if __cplusplus >= 201103L class A { diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6744ce1cad174e2ac154e118868ec2c841407bb3 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -Wno-unused -fsyntax-only %s -verify + +struct A { + void operator*(); + void operator+(); + void operator-(); + void operator!(); + void operator~(); + void operator&(); + void operator++(); + void operator--(); +}; + +struct B { }; + +template +void dependent(T t, T* pt, T U::* mpt, T(&ft)(), T(&at)[4]) { + *t; + +t; + -t; + !t; + ~t; + &t; + ++t; + --t; + + *pt; + +pt; + -pt; // expected-error {{invalid argument type 'T *' to unary expression}} + !pt; + ~pt; // expected-error {{invalid argument type 'T *' to unary expression}} + &pt; + ++pt; + --pt; + + *mpt; // expected-error {{indirection requires pointer operand ('T U::*' invalid)}} + +mpt; // expected-error {{invalid argument type 'T U::*' to unary expression}} + -mpt; // expected-error {{invalid argument type 'T U::*' to unary expression}} + !mpt; + ~mpt; // expected-error {{invalid argument type 'T U::*' to unary expression}} + &mpt; + ++mpt; // expected-error {{cannot increment value of type 'T U::*'}} + --mpt; // expected-error {{cannot decrement value of type 'T U::*'}} + + *ft; + +ft; + -ft; // expected-error {{invalid argument type 'T (*)()' to unary expression}} + !ft; + ~ft; // expected-error {{invalid argument type 'T (*)()' to unary expression}} + &ft; + ++ft; // expected-error {{cannot increment value of type 'T ()'}} + --ft; // expected-error {{cannot decrement value of type 'T ()'}} + + *at; + +at; + -at; // expected-error {{invalid argument type 'T *' to unary expression}} + !at; + ~at; // expected-error {{invalid argument type 'T *' to unary expression}} + &at; + ++at; // expected-error {{cannot increment value of type 'T[4]'}} + --at; // expected-error {{cannot decrement value of type 'T[4]'}} +} + +// Make sure we only emit diagnostics once. +template void dependent(A t, A* pt, A B::* mpt, A(&ft)(), A(&at)[4]); diff --git a/clang/test/CXX/over/over.built/ast.cpp b/clang/test/CXX/over/over.built/ast.cpp index 56a63431269f300e559b256809d344320de14758..78f86edb1e96162aca44fd7091706d8d63e40de0 100644 --- a/clang/test/CXX/over/over.built/ast.cpp +++ b/clang/test/CXX/over/over.built/ast.cpp @@ -1,41 +1,139 @@ -// RUN: %clang_cc1 -std=c++17 -ast-dump %s -ast-dump-filter Test | FileCheck %s +// RUN: %clang_cc1 -std=c++17 -Wno-unused -ast-dump %s -ast-dump-filter Test | FileCheck %s -struct A{}; +namespace Test { + template + void Unary(T t, T* pt, T U::* mpt, T(&ft)(), T(&at)[4]) { + // CHECK: UnaryOperator {{.*}} '' lvalue prefix '*' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + *t; -template -auto Test(T* pt, U* pu) { - // CHECK: UnaryOperator {{.*}} '' lvalue prefix '*' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - (void)*pt; + // CHECK: UnaryOperator {{.*}} '' prefix '+' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + +t; - // CHECK: UnaryOperator {{.*}} '' lvalue prefix '++' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - (void)(++pt); + // CHECK: UnaryOperator {{.*}} '' prefix '-' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + -t; - // CHECK: UnaryOperator {{.*}} '' prefix '+' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - (void)(+pt); + // CHECK: UnaryOperator {{.*}} '' prefix '!' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + !t; - // CHECK: BinaryOperator {{.*}} '' '+' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3 - (void)(pt + 3); + // CHECK: UnaryOperator {{.*}} '' prefix '~' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + ~t; - // CHECK: BinaryOperator {{.*}} '' '-' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - (void)(pt - pt); + // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + &t; - // CHECK: BinaryOperator {{.*}} '' '-' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' - (void)(pt - pu); + // CHECK: UnaryOperator {{.*}} '' lvalue prefix '++' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + ++t; - // CHECK: BinaryOperator {{.*}} '' '==' - // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' - (void)(pt == pu); + // CHECK: UnaryOperator {{.*}} '' lvalue prefix '--' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T' + --t; -} + // CHECK: UnaryOperator {{.*}} 'T' lvalue prefix '*' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + *pt; + // CHECK: UnaryOperator {{.*}} 'T *' prefix '+' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + +pt; + // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + !pt; + + // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + &pt; + + // CHECK: UnaryOperator {{.*}} 'T *' lvalue prefix '++' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + ++pt; + + // CHECK: UnaryOperator {{.*}} 'T *' lvalue prefix '--' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + --pt; + + // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T U::*' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T U::*' lvalue ParmVar {{.*}} 'mpt' 'T U::*' + !mpt; + + // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T U::*' lvalue ParmVar {{.*}} 'mpt' 'T U::*' + &mpt; + + // CHECK: UnaryOperator {{.*}} 'T ()' lvalue prefix '*' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T (*)()' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' + *ft; + + // CHECK: UnaryOperator {{.*}} 'T (*)()' prefix '+' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T (*)()' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' + +ft; + + // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T (*)()' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' + !ft; + + // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()' + &ft; + + // CHECK: UnaryOperator {{.*}} 'T' lvalue prefix '*' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' + *at; + + // CHECK: UnaryOperator {{.*}} 'T *' prefix '+' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' + +at; + + // CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' + !at; + + // CHECK: UnaryOperator {{.*}} '' prefix '&' cannot overflow + // CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]' + &at; + } + + template + void Binary(T* pt, U* pu) { + // CHECK: BinaryOperator {{.*}} '' '+' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3 + pt + 3; + + // CHECK: BinaryOperator {{.*}} '' '-' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + pt - pt; + + // CHECK: BinaryOperator {{.*}} '' '-' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' + pt - pu; + + // CHECK: BinaryOperator {{.*}} '' '==' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' + pt == pu; + } +} // namespace Test diff --git a/clang/test/CXX/over/over.built/p10.cpp b/clang/test/CXX/over/over.built/p10.cpp index 678056da5820570a026e9a20233fc9faa1e11ba5..8ff2396d0b6f95fcde6178572542273558862dfb 100644 --- a/clang/test/CXX/over/over.built/p10.cpp +++ b/clang/test/CXX/over/over.built/p10.cpp @@ -15,6 +15,6 @@ void f(int i, float f, bool b, char c, int* pi, A* pa, T* pt) { (void)-pi; // expected-error {{invalid argument type}} (void)-pa; // expected-error {{invalid argument type}} - (void)-pt; // FIXME: we should be able to give an error here. + (void)-pt; // expected-error {{invalid argument type}} } diff --git a/clang/test/CXX/over/over.built/p11.cpp b/clang/test/CXX/over/over.built/p11.cpp index 7ebf16b95439f6dd5c88f86c2984c3ef2f9a495b..f7a741db726def6467623bf35d776b79e772e9fc 100644 --- a/clang/test/CXX/over/over.built/p11.cpp +++ b/clang/test/CXX/over/over.built/p11.cpp @@ -7,6 +7,6 @@ void f(int i, float f, bool b, char c, int* pi, T* pt) { (void)~b; (void)~c; (void)~pi; // expected-error {{invalid argument type}} - (void)~pt; // FIXME: we should be able to give an error here. + (void)~pt; // expected-error {{invalid argument type}} } diff --git a/clang/test/CXX/over/over.oper/over.oper.general/p1.cpp b/clang/test/CXX/over/over.oper/over.oper.general/p1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d49fb0645751a46e883655c8864538576b5f89d0 --- /dev/null +++ b/clang/test/CXX/over/over.oper/over.oper.general/p1.cpp @@ -0,0 +1,173 @@ +// RUN: %clang_cc1 -std=c++20 -verify -Wno-unused %s + +template +void operator->*(T, U); + +template +void operator+(T, U); + +template +void operator-(T, U); + +template +void operator*(T, U); + +template +void operator/(T, U); + +template +void operator%(T, U); + +template +void operator^(T, U); + +template +void operator&(T, U); + +template +void operator|(T, U); + +template +void operator+=(T, U); + +template +void operator-=(T, U); + +template +void operator*=(T, U); + +template +void operator/=(T, U); + +template +void operator%=(T, U); + +template +void operator^=(T, U); + +template +void operator&=(T, U); + +template +void operator|=(T, U); + +template +void operator==(T, U); + +template +void operator!=(T, U); + +template +void operator<(T, U); + +template +void operator>(T, U); + +template +void operator<=(T, U); + +template +void operator>=(T, U); + +template +void operator<=>(T, U); + +template +void operator&&(T, U); + +template +void operator||(T, U); + +template +void operator<<(T, U); + +template +void operator>>(T, U); + +template +void operator<<=(T, U); + +template +void operator>>=(T, U); + +template +void operator,(T, U); + +template +void operator*(T); + +template +void operator&(T); + +template +void operator+(T); + +template +void operator-(T); + +template +void operator!(T); + +template +void operator~(T); + +template +void operator++(T); + +template +void operator--(T); + +template +void operator++(T, int); + +template +void operator--(T, int); + +template +void f(int *x) { + [&](auto *y) { + *y; + &y; + +y; + -y; // expected-error {{invalid argument type 'auto *' to unary expression}} + !y; + ~y; // expected-error {{invalid argument type 'auto *' to unary expression}} + ++y; + --y; + y++; + y--; + y->*x; + y + x; + y - x; + y * x; + y / x; + y % x; + y ^ x; + y & x; + y | x; + y += x; + y -= x; + y *= x; + y /= x; + y %= x; + y ^= x; + y &= x; + y |= x; + y == x; + y != x; + y < x; + y > x; + y <= x; + y >= x; + y <=> x; + y && x; + y || x; + y << x; + y >> x; + y <<= x; + y >>= x; + y, x; + }; +} + +template void f(int*); diff --git a/clang/test/CXX/special/class.temporary/p6.cpp b/clang/test/CXX/special/class.temporary/p6.cpp index a6d2adfd1fd2c5bac6d063cdd839011bb8828b13..5554363cc69abb5190169e6c181d3c84756cf83d 100644 --- a/clang/test/CXX/special/class.temporary/p6.cpp +++ b/clang/test/CXX/special/class.temporary/p6.cpp @@ -269,40 +269,6 @@ void init_capture_init_list() { // CHECK: } } -void check_dr1815() { // dr1815: yes -#if __cplusplus >= 201402L - - struct A { - int &&r = 0; - ~A() {} - }; - - struct B { - A &&a = A{}; - ~B() {} - }; - B a = {}; - - // CHECK: call {{.*}}block_scope_begin_function - extern void block_scope_begin_function(); - extern void block_scope_end_function(); - block_scope_begin_function(); - { - // CHECK: call void @_ZZ12check_dr1815vEN1BD1Ev - // CHECK: call void @_ZZ12check_dr1815vEN1AD1Ev - B b = {}; - } - // CHECK: call {{.*}}block_scope_end_function - block_scope_end_function(); - - // CHECK: call {{.*}}some_other_function - extern void some_other_function(); - some_other_function(); - // CHECK: call void @_ZZ12check_dr1815vEN1BD1Ev - // CHECK: call void @_ZZ12check_dr1815vEN1AD1Ev -#endif -} - namespace P2718R0 { namespace basic { template using T2 = std::list; diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..df1bbd5fe8128827f55152d45125bc6637417f85 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s +// expected-no-diagnostics + +namespace GH77377 { + template + concept C = sizeof(T) == sizeof(int); + + template + struct A; + + template + struct A; +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cc1d4ecda2ecca034e699864800449ead2af8e1e --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics + +template +struct A { }; + +constexpr A a; +constexpr A b; + +constexpr int* x = nullptr; +constexpr short* y = nullptr; + +namespace ExplicitArgs { + template + constexpr int f(U) noexcept(noexcept(T())) { + return 0; + } + + template + constexpr int f(T*) noexcept { + return 1; + } + + template<> + constexpr int f(int*) noexcept { + return 2; + } + + static_assert(f(1) == 0); + static_assert(f(y) == 1); + static_assert(f(x) == 2); + + template + constexpr int g(U*) noexcept(noexcept(T())) { + return 3; + } + + template + constexpr int g(T) noexcept { + return 4; + } + + template<> + constexpr int g(int*) noexcept { + return 5; + } + + static_assert(g(y) == 3); + static_assert(g(1) == 4); + static_assert(g(x) == 5); +} // namespace ExplicitArgs + +namespace DeducedArgs { + template + constexpr int f(T, A) noexcept(B) { + return 0; + } + + template + constexpr int f(T*, A) noexcept(B && B) { + return 1; + } + + template<> + constexpr int f(int*, A) { + return 2; + } + + static_assert(f(x, a) == 0); + static_assert(f(y, a) == 1); + static_assert(f(x, a) == 2); +} // namespace DeducedArgs diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp index 3ca7c6c7eb8eebf5e82b663cf5ee94fc3fa2c727..982e5372f5b0c83e4fc9a2a0e7a94b6c30b9e1bc 100644 --- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp @@ -357,17 +357,14 @@ namespace N0 { a->A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} a->B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} - // FIXME: An overloaded unary 'operator*' is built for these - // even though the operand is a pointer (to a dependent type). - // Type::isOverloadableType should return false for such cases. - (*this).x4; - (*this).B::x4; - (*this).A::x4; - (*this).B::A::x4; - (*this).f4(); - (*this).B::f4(); - (*this).A::f4(); - (*this).B::A::f4(); + (*this).x4; // expected-error{{no member named 'x4' in 'B'}} + (*this).B::x4; // expected-error{{no member named 'x4' in 'B'}} + (*this).A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} + (*this).B::A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} + (*this).f4(); // expected-error{{no member named 'f4' in 'B'}} + (*this).B::f4(); // expected-error{{no member named 'f4' in 'B'}} + (*this).A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} + (*this).B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} b.x4; // expected-error{{no member named 'x4' in 'B'}} b.B::x4; // expected-error{{no member named 'x4' in 'B'}} @@ -399,15 +396,13 @@ namespace N1 { f<0>(); this->f<0>(); a->f<0>(); - // FIXME: This should not require 'template'! - (*this).f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} + (*this).f<0>(); b.f<0>(); x.f<0>(); this->x.f<0>(); a->x.f<0>(); - // FIXME: This should not require 'template'! - (*this).x.f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} + (*this).x.f<0>(); b.x.f<0>(); // FIXME: None of these should require 'template'! diff --git a/clang/test/CodeGen/RISCV/riscv-inline-asm.c b/clang/test/CodeGen/RISCV/riscv-inline-asm.c index 3565705dea71306be02259510f3f4b5cbe037be5..ed97add95e71169869f8ee306d12612375b83182 100644 --- a/clang/test/CodeGen/RISCV/riscv-inline-asm.c +++ b/clang/test/CodeGen/RISCV/riscv-inline-asm.c @@ -49,9 +49,9 @@ extern int var, arr[2][2]; struct Pair { int a, b; } pair; // CHECK-LABEL: test_s( -// CHECK: call void asm sideeffect "// $0 $1 $2", "s,s,s"(ptr nonnull @var, ptr nonnull getelementptr inbounds ([2 x [2 x i32]], ptr @arr, {{.*}}), ptr nonnull @test_s) -// CHECK: call void asm sideeffect "// $0", "s"(ptr nonnull getelementptr inbounds (%struct.Pair, ptr @pair, {{.*}})) -// CHECK: call void asm sideeffect "// $0 $1 $2", "S,S,S"(ptr nonnull @var, ptr nonnull getelementptr inbounds ([2 x [2 x i32]], ptr @arr, {{.*}}), ptr nonnull @test_s) +// CHECK: call void asm sideeffect "// $0 $1 $2", "s,s,s"(ptr nonnull @var, ptr nonnull getelementptr inbounds (i8, ptr @arr, {{.*}}), ptr nonnull @test_s) +// CHECK: call void asm sideeffect "// $0", "s"(ptr nonnull getelementptr inbounds (i8, ptr @pair, {{.*}})) +// CHECK: call void asm sideeffect "// $0 $1 $2", "S,S,S"(ptr nonnull @var, ptr nonnull getelementptr inbounds (i8, ptr @arr, {{.*}}), ptr nonnull @test_s) void test_s(void) { asm("// %0 %1 %2" :: "s"(&var), "s"(&arr[1][1]), "s"(test_s)); asm("// %0" :: "s"(&pair.b)); diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_add_sub_za16.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_add_sub_za16.c new file mode 100644 index 0000000000000000000000000000000000000000..9a8aa448d3780dc600f91427094442bd9dd1aa67 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_add_sub_za16.c @@ -0,0 +1,193 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sme-f16f16 -target-feature +b16b16 -O2 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -x c++ -fclang-abi-compat=latest -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +b16b16 -O2 -Werror -Wall -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-CXX +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -fclang-abi-compat=latest -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +b16b16 -O2 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -x c++ -fclang-abi-compat=latest -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sme-f16f16 -target-feature +b16b16 -O2 -Werror -Wall -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-CXX + +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sme-f16f16 -target-feature +b16b16 -O2 -S -Werror -Wall -o /dev/null + +// REQUIRES: aarch64-registered-target + +#include + +#ifdef SVE_OVERLOADED_FORMS +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3) A1##A2##A3 +#endif + +// CHECK-LABEL: define dso_local void @test_svadd_za16_vg1x2_f16( +// CHECK-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZN]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZN]], i64 8) +// CHECK-NEXT: tail call void @llvm.aarch64.sme.add.za16.vg1x2.nxv8f16(i32 [[SLICE]], [[TMP0]], [[TMP1]]) +// CHECK-NEXT: ret void +// +// CHECK-CXX-LABEL: define dso_local void @_Z25test_svadd_za16_vg1x2_f16j13svfloat16x2_t( +// CHECK-CXX-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-CXX-NEXT: entry: +// CHECK-CXX-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZN]], i64 0) +// CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZN]], i64 8) +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.add.za16.vg1x2.nxv8f16(i32 [[SLICE]], [[TMP0]], [[TMP1]]) +// CHECK-CXX-NEXT: ret void +// +void test_svadd_za16_vg1x2_f16(uint32_t slice, svfloat16x2_t zn) __arm_streaming __arm_inout("za") { + SVE_ACLE_FUNC(svadd_za16,_f16,_vg1x2)(slice, zn); +} + +// CHECK-LABEL: define dso_local void @test_svadd_za16_vg1x4_f16( +// CHECK-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 24) +// CHECK-NEXT: tail call void @llvm.aarch64.sme.add.za16.vg1x4.nxv8f16(i32 [[SLICE]], [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret void +// +// CHECK-CXX-LABEL: define dso_local void @_Z25test_svadd_za16_vg1x4_f16j13svfloat16x4_t( +// CHECK-CXX-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-CXX-NEXT: entry: +// CHECK-CXX-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 0) +// CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 8) +// CHECK-CXX-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 16) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 24) +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.add.za16.vg1x4.nxv8f16(i32 [[SLICE]], [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-CXX-NEXT: ret void +// +void test_svadd_za16_vg1x4_f16(uint32_t slice, svfloat16x4_t zn) __arm_streaming __arm_inout("za") { + SVE_ACLE_FUNC(svadd_za16,_f16,_vg1x4)(slice, zn); +} + +// CHECK-LABEL: define dso_local void @test_svsub_za16_vg1x2_f16( +// CHECK-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZN]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZN]], i64 8) +// CHECK-NEXT: tail call void @llvm.aarch64.sme.sub.za16.vg1x2.nxv8f16(i32 [[SLICE]], [[TMP0]], [[TMP1]]) +// CHECK-NEXT: ret void +// +// CHECK-CXX-LABEL: define dso_local void @_Z25test_svsub_za16_vg1x2_f16j13svfloat16x2_t( +// CHECK-CXX-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-CXX-NEXT: entry: +// CHECK-CXX-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZN]], i64 0) +// CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZN]], i64 8) +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.sub.za16.vg1x2.nxv8f16(i32 [[SLICE]], [[TMP0]], [[TMP1]]) +// CHECK-CXX-NEXT: ret void +// +void test_svsub_za16_vg1x2_f16(uint32_t slice, svfloat16x2_t zn) __arm_streaming __arm_inout("za") { + SVE_ACLE_FUNC(svsub_za16,_f16,_vg1x2)(slice, zn); +} + +// CHECK-LABEL: define dso_local void @test_svsub_za16_vg1x4_f16( +// CHECK-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 24) +// CHECK-NEXT: tail call void @llvm.aarch64.sme.sub.za16.vg1x4.nxv8f16(i32 [[SLICE]], [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret void +// +// CHECK-CXX-LABEL: define dso_local void @_Z25test_svsub_za16_vg1x4_f16j13svfloat16x4_t( +// CHECK-CXX-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-CXX-NEXT: entry: +// CHECK-CXX-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 0) +// CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 8) +// CHECK-CXX-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 16) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZN]], i64 24) +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.sub.za16.vg1x4.nxv8f16(i32 [[SLICE]], [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-CXX-NEXT: ret void +// +void test_svsub_za16_vg1x4_f16(uint32_t slice, svfloat16x4_t zn) __arm_streaming __arm_inout("za") { + SVE_ACLE_FUNC(svsub_za16,_f16,_vg1x4)(slice, zn); +} + +// CHECK-LABEL: define dso_local void @test_svadd_za16_vg1x2_bf16( +// CHECK-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZN]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZN]], i64 8) +// CHECK-NEXT: tail call void @llvm.aarch64.sme.add.za16.vg1x2.nxv8bf16(i32 [[SLICE]], [[TMP0]], [[TMP1]]) +// CHECK-NEXT: ret void +// +// CHECK-CXX-LABEL: define dso_local void @_Z26test_svadd_za16_vg1x2_bf16j14svbfloat16x2_t( +// CHECK-CXX-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-CXX-NEXT: entry: +// CHECK-CXX-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZN]], i64 0) +// CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZN]], i64 8) +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.add.za16.vg1x2.nxv8bf16(i32 [[SLICE]], [[TMP0]], [[TMP1]]) +// CHECK-CXX-NEXT: ret void +// +void test_svadd_za16_vg1x2_bf16(uint32_t slice, svbfloat16x2_t zn) __arm_streaming __arm_inout("za") { + SVE_ACLE_FUNC(svadd_za16,_bf16,_vg1x2)(slice, zn); +} + +// CHECK-LABEL: define dso_local void @test_svadd_za16_vg1x4_bf16( +// CHECK-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 24) +// CHECK-NEXT: tail call void @llvm.aarch64.sme.add.za16.vg1x4.nxv8bf16(i32 [[SLICE]], [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret void +// +// CHECK-CXX-LABEL: define dso_local void @_Z26test_svadd_za16_vg1x4_bf16j14svbfloat16x4_t( +// CHECK-CXX-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-CXX-NEXT: entry: +// CHECK-CXX-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 0) +// CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 8) +// CHECK-CXX-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 16) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 24) +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.add.za16.vg1x4.nxv8bf16(i32 [[SLICE]], [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-CXX-NEXT: ret void +// +void test_svadd_za16_vg1x4_bf16(uint32_t slice, svbfloat16x4_t zn) __arm_streaming __arm_inout("za") { + SVE_ACLE_FUNC(svadd_za16,_bf16,_vg1x4)(slice, zn); +} + +// CHECK-LABEL: define dso_local void @test_svsub_za16_vg1x2_bf16( +// CHECK-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZN]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZN]], i64 8) +// CHECK-NEXT: tail call void @llvm.aarch64.sme.sub.za16.vg1x2.nxv8bf16(i32 [[SLICE]], [[TMP0]], [[TMP1]]) +// CHECK-NEXT: ret void +// +// CHECK-CXX-LABEL: define dso_local void @_Z26test_svsub_za16_vg1x2_bf16j14svbfloat16x2_t( +// CHECK-CXX-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-CXX-NEXT: entry: +// CHECK-CXX-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZN]], i64 0) +// CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZN]], i64 8) +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.sub.za16.vg1x2.nxv8bf16(i32 [[SLICE]], [[TMP0]], [[TMP1]]) +// CHECK-CXX-NEXT: ret void +// +void test_svsub_za16_vg1x2_bf16(uint32_t slice, svbfloat16x2_t zn) __arm_streaming __arm_inout("za") { + SVE_ACLE_FUNC(svsub_za16,_bf16,_vg1x2)(slice, zn); +} + +// CHECK-LABEL: define dso_local void @test_svsub_za16_vg1x4_bf16( +// CHECK-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 24) +// CHECK-NEXT: tail call void @llvm.aarch64.sme.sub.za16.vg1x4.nxv8bf16(i32 [[SLICE]], [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret void +// +// CHECK-CXX-LABEL: define dso_local void @_Z26test_svsub_za16_vg1x4_bf16j14svbfloat16x4_t( +// CHECK-CXX-SAME: i32 noundef [[SLICE:%.*]], [[ZN:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-CXX-NEXT: entry: +// CHECK-CXX-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 0) +// CHECK-CXX-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 8) +// CHECK-CXX-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 16) +// CHECK-CXX-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZN]], i64 24) +// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.sub.za16.vg1x4.nxv8bf16(i32 [[SLICE]], [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-CXX-NEXT: ret void +// +void test_svsub_za16_vg1x4_bf16(uint32_t slice, svbfloat16x4_t zn) __arm_streaming __arm_inout("za") { + SVE_ACLE_FUNC(svsub_za16,_bf16,_vg1x4)(slice, zn); +} diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_max.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_max.c index 8e696f1d1fa4c4c8665dcc2541432fe1f88ec91e..2b9343a2c6b6cd178b6d5d63e5eba14bec0f0b88 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_max.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_max.c @@ -1,9 +1,9 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s // REQUIRES: aarch64-registered-target #include @@ -224,6 +224,32 @@ svuint64x2_t test_svmax_single_u64_x2(svuint64x2_t zdn, svuint64_t zm) __arm_str return SVE_ACLE_FUNC(svmax,_single_u64_x2)(zdn, zm); } +// CHECK-LABEL: @test_svmax_single_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fmax.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z25test_svmax_single_bf16_x214svbfloat16x2_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fmax.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svbfloat16x2_t test_svmax_single_bf16_x2(svbfloat16x2_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmax,_single_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svmax_single_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -608,6 +634,44 @@ svuint64x4_t test_svmax_single_u64_x4(svuint64x4_t zdn, svuint64_t zm) __arm_str return SVE_ACLE_FUNC(svmax,_single_u64_x4)(zdn, zm); } +// CHECK-LABEL: @test_svmax_single_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmax.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CHECK-NEXT: ret [[TMP12]] +// +// CPP-CHECK-LABEL: @_Z25test_svmax_single_bf16_x414svbfloat16x4_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmax.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP12]] +// +svbfloat16x4_t test_svmax_single_bf16_x4(svbfloat16x4_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmax,_single_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svmax_single_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) @@ -964,6 +1028,36 @@ svuint64x2_t test_svmax_u64_x2(svuint64x2_t zdn, svuint64x2_t zm) __arm_streamin return SVE_ACLE_FUNC(svmax,_u64_x2)(zdn, zm); } +// CHECK-LABEL: @test_svmax_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fmax.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z18test_svmax_bf16_x214svbfloat16x2_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fmax.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svbfloat16x2_t test_svmax_bf16_x2(svbfloat16x2_t zdn, svbfloat16x2_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmax,_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svmax_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -1424,6 +1518,52 @@ svuint64x4_t test_svmax_u64_x4(svuint64x4_t zdn, svuint64x4_t zm) __arm_streamin return SVE_ACLE_FUNC(svmax,_u64_x4)(zdn, zm); } +// CHECK-LABEL: @test_svmax_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmax.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CHECK-NEXT: ret [[TMP16]] +// +// CPP-CHECK-LABEL: @_Z18test_svmax_bf16_x414svbfloat16x4_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmax.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CPP-CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CPP-CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CPP-CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CPP-CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP16]] +// +svbfloat16x4_t test_svmax_bf16_x4(svbfloat16x4_t zdn, svbfloat16x4_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmax,_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svmax_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_maxnm.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_maxnm.c index a956235034e14ffd26f7d73649f48e21ddaf3a36..ac2e20cf98b862691a0747decb931338e0e8167d 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_maxnm.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_maxnm.c @@ -1,11 +1,11 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s #include #ifdef SVE_OVERLOADED_FORMS @@ -17,6 +17,32 @@ // Single, x2 +// CHECK-LABEL: @test_svmaxnm_single_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fmaxnm.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z27test_svmaxnm_single_bf16_x214svbfloat16x2_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fmaxnm.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svbfloat16x2_t test_svmaxnm_single_bf16_x2(svbfloat16x2_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmaxnm,_single_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svmaxnm_single_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -97,6 +123,44 @@ svfloat64x2_t test_svmaxnm_single_f64_x2(svfloat64x2_t zdn, svfloat64_t zm) __ar // Single, x4 +// CHECK-LABEL: @test_svmaxnm_single_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmaxnm.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CHECK-NEXT: ret [[TMP12]] +// +// CPP-CHECK-LABEL: @_Z27test_svmaxnm_single_bf16_x414svbfloat16x4_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmaxnm.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP12]] +// +svbfloat16x4_t test_svmaxnm_single_bf16_x4(svbfloat16x4_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmaxnm,_single_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svmaxnm_single_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) @@ -213,6 +277,36 @@ svfloat64x4_t test_svmaxnm_single_f64_x4(svfloat64x4_t zdn, svfloat64_t zm) __ar // Multi, x2 +// CHECK-LABEL: @test_svmaxnm_multi_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fmaxnm.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z26test_svmaxnm_multi_bf16_x214svbfloat16x2_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fmaxnm.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svbfloat16x2_t test_svmaxnm_multi_bf16_x2(svbfloat16x2_t zdn, svbfloat16x2_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmaxnm,_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svmaxnm_multi_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -305,6 +399,52 @@ svfloat64x2_t test_svmaxnm_multi_f64_x2(svfloat64x2_t zdn, svfloat64x2_t zm) __a // Multi, x4 +// CHECK-LABEL: @test_svmaxnm_multi_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmaxnm.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CHECK-NEXT: ret [[TMP16]] +// +// CPP-CHECK-LABEL: @_Z26test_svmaxnm_multi_bf16_x414svbfloat16x4_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmaxnm.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CPP-CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CPP-CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CPP-CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CPP-CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP16]] +// +svbfloat16x4_t test_svmaxnm_multi_bf16_x4(svbfloat16x4_t zdn, svbfloat16x4_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmaxnm,_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svmaxnm_multi_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_min.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_min.c index 860e6237bb9c81ef4ad877a6d29e3b2a31b0ba86..dda0837cf1f3cbf4b00cd800cfbe36991ac5ee51 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_min.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_min.c @@ -1,9 +1,9 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s // REQUIRES: aarch64-registered-target #include @@ -224,6 +224,32 @@ svuint64x2_t test_svmin_single_u64_x2(svuint64x2_t zdn, svuint64_t zm) __arm_str return SVE_ACLE_FUNC(svmin,_single_u64_x2)(zdn, zm); } +// CHECK-LABEL: @test_svmin_single_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fmin.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z25test_svmin_single_bf16_x214svbfloat16x2_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fmin.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svbfloat16x2_t test_svmin_single_bf16_x2(svbfloat16x2_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmin,_single_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svmin_single_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -608,6 +634,44 @@ svuint64x4_t test_svmin_single_u64_x4(svuint64x4_t zdn, svuint64_t zm) __arm_str return SVE_ACLE_FUNC(svmin,_single_u64_x4)(zdn, zm); } +// CHECK-LABEL: @test_svmin_single_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmin.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CHECK-NEXT: ret [[TMP12]] +// +// CPP-CHECK-LABEL: @_Z25test_svmin_single_bf16_x414svbfloat16x4_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmin.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP12]] +// +svbfloat16x4_t test_svmin_single_bf16_x4(svbfloat16x4_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmin,_single_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svmin_single_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) @@ -964,6 +1028,36 @@ svuint64x2_t test_svmin_u64_x2(svuint64x2_t zdn, svuint64x2_t zm) __arm_streamin return SVE_ACLE_FUNC(svmin,_u64_x2)(zdn, zm); } +// CHECK-LABEL: @test_svmin_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fmin.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z18test_svmin_bf16_x214svbfloat16x2_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fmin.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svbfloat16x2_t test_svmin_bf16_x2(svbfloat16x2_t zdn, svbfloat16x2_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmin,_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svmin_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -1424,6 +1518,52 @@ svuint64x4_t test_svmin_u64_x4(svuint64x4_t zdn, svuint64x4_t zm) __arm_streamin return SVE_ACLE_FUNC(svmin,_u64_x4)(zdn, zm); } +// CHECK-LABEL: @test_svmin_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmin.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CHECK-NEXT: ret [[TMP16]] +// +// CPP-CHECK-LABEL: @_Z18test_svmin_bf16_x414svbfloat16x4_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmin.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CPP-CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CPP-CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CPP-CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CPP-CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP16]] +// +svbfloat16x4_t test_svmin_bf16_x4(svbfloat16x4_t zdn, svbfloat16x4_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmin,_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svmin_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_minnm.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_minnm.c index e34b9d98eff33d4be7987068b0fd4e6028cf175c..23378ffdf85d4ec7072d1f10824cd4a72d1037e5 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_minnm.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_minnm.c @@ -1,11 +1,11 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s #include #ifdef SVE_OVERLOADED_FORMS @@ -17,6 +17,32 @@ // Single, x2 +// CHECK-LABEL: @test_svminnm_single_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fminnm.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z27test_svminnm_single_bf16_x214svbfloat16x2_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fminnm.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svbfloat16x2_t test_svminnm_single_bf16_x2(svbfloat16x2_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svminnm,_single_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svminnm_single_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -97,6 +123,44 @@ svfloat64x2_t test_svminnm_single_f64_x2(svfloat64x2_t zdn, svfloat64_t zm) __ar // Single, x4 +// CHECK-LABEL: @test_svminnm_single_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fminnm.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CHECK-NEXT: ret [[TMP12]] +// +// CPP-CHECK-LABEL: @_Z27test_svminnm_single_bf16_x414svbfloat16x4_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fminnm.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP12]] +// +svbfloat16x4_t test_svminnm_single_bf16_x4(svbfloat16x4_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svminnm,_single_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svminnm_single_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) @@ -213,6 +277,36 @@ svfloat64x4_t test_svminnm_single_f64_x4(svfloat64x4_t zdn, svfloat64_t zm) __ar // Multi, x2 +// CHECK-LABEL: @test_svminnm_multi_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fminnm.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z26test_svminnm_multi_bf16_x214svbfloat16x2_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fminnm.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svbfloat16x2_t test_svminnm_multi_bf16_x2(svbfloat16x2_t zdn, svbfloat16x2_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svminnm,_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svminnm_multi_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -305,6 +399,52 @@ svfloat64x2_t test_svminnm_multi_f64_x2(svfloat64x2_t zdn, svfloat64x2_t zm) __a // Multi, x4 +// CHECK-LABEL: @test_svminnm_multi_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fminnm.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CHECK-NEXT: ret [[TMP16]] +// +// CPP-CHECK-LABEL: @_Z26test_svminnm_multi_bf16_x414svbfloat16x4_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fminnm.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CPP-CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CPP-CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CPP-CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CPP-CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP16]] +// +svbfloat16x4_t test_svminnm_multi_bf16_x4(svbfloat16x4_t zdn, svbfloat16x4_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svminnm,_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svminnm_multi_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_reinterpret_svcount_svbool.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_reinterpret_svcount_svbool.c index b3d5f4a4c4a537941b82f4f65a6ee1786cd00980..c442d2c0c47502f1811841edad7b57a12ff0e01a 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_reinterpret_svcount_svbool.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_reinterpret_svcount_svbool.c @@ -9,6 +9,12 @@ #include +#if defined __ARM_FEATURE_SME +#define MODE_ATTR __arm_streaming +#else +#define MODE_ATTR +#endif + #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin.§ #define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 @@ -26,7 +32,7 @@ // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.taarch64.svcountt(target("aarch64.svcount") [[CNT:%.*]]) // CPP-CHECK-NEXT: ret [[TMP0]] // -svbool_t test_svreinterpret_svbool_svcnt(svcount_t cnt) __arm_streaming_compatible +svbool_t test_svreinterpret_svbool_svcnt(svcount_t cnt) MODE_ATTR { return SVE_ACLE_FUNC(svreinterpret,_b,,)(cnt); } @@ -41,7 +47,7 @@ svbool_t test_svreinterpret_svbool_svcnt(svcount_t cnt) __arm_streaming_compatib // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt( [[PG:%.*]]) // CPP-CHECK-NEXT: ret target("aarch64.svcount") [[TMP0]] // -svcount_t test_svreinterpret_svcnt_svbool(svbool_t pg) __arm_streaming_compatible +svcount_t test_svreinterpret_svcnt_svbool(svbool_t pg) MODE_ATTR { return SVE_ACLE_FUNC(svreinterpret,_c,,)(pg); } diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_revd.c b/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_revd.c index 128a7eb102da9e923750092638ebb12e970b7473..b4432c4f447723cb7b8de3194fb9a671de489e6f 100644 --- a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_revd.c +++ b/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_revd.c @@ -12,6 +12,12 @@ // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +bf16 -S -disable-O0-optnone -Werror -o /dev/null %s #include +#if defined __ARM_FEATURE_SME +#define MODE_ATTR __arm_streaming +#else +#define MODE_ATTR +#endif + #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin. #define SVE_ACLE_FUNC(A1, A2_UNUSED, A3, A4_UNUSED) A1##A3 @@ -29,7 +35,7 @@ // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.revd.nxv16i8( zeroinitializer, [[PG:%.*]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP0]] // -svint8_t test_svrevd_s8_z(svbool_t pg, svint8_t op) { +svint8_t test_svrevd_s8_z(svbool_t pg, svint8_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _s8, _z, )(pg, op); } @@ -45,7 +51,7 @@ svint8_t test_svrevd_s8_z(svbool_t pg, svint8_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv8i16( zeroinitializer, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svint16_t test_svrevd_s16_z(svbool_t pg, svint16_t op) { +svint16_t test_svrevd_s16_z(svbool_t pg, svint16_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _s16, _z, )(pg, op); } @@ -61,7 +67,7 @@ svint16_t test_svrevd_s16_z(svbool_t pg, svint16_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv4i32( zeroinitializer, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svint32_t test_svrevd_s32_z(svbool_t pg, svint32_t op) { +svint32_t test_svrevd_s32_z(svbool_t pg, svint32_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _s32, _z, )(pg, op); } @@ -77,7 +83,7 @@ svint32_t test_svrevd_s32_z(svbool_t pg, svint32_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv2i64( zeroinitializer, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svint64_t test_svrevd_s64_z(svbool_t pg, svint64_t op) { +svint64_t test_svrevd_s64_z(svbool_t pg, svint64_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _s64, _z, )(pg, op); } @@ -91,7 +97,7 @@ svint64_t test_svrevd_s64_z(svbool_t pg, svint64_t op) { // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.revd.nxv16i8( zeroinitializer, [[PG:%.*]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP0]] // -svuint8_t test_svrevd_u8_z(svbool_t pg, svuint8_t op) { +svuint8_t test_svrevd_u8_z(svbool_t pg, svuint8_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _u8, _z, )(pg, op); } // CHECK-LABEL: @test_svrevd_u16_z( @@ -106,7 +112,7 @@ svuint8_t test_svrevd_u8_z(svbool_t pg, svuint8_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv8i16( zeroinitializer, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svuint16_t test_svrevd_u16_z(svbool_t pg, svuint16_t op) { +svuint16_t test_svrevd_u16_z(svbool_t pg, svuint16_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _u16, _z, )(pg, op); } @@ -122,7 +128,7 @@ svuint16_t test_svrevd_u16_z(svbool_t pg, svuint16_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv4i32( zeroinitializer, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svuint32_t test_svrevd_u32_z(svbool_t pg, svuint32_t op) { +svuint32_t test_svrevd_u32_z(svbool_t pg, svuint32_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _u32, _z, )(pg, op); } @@ -138,7 +144,7 @@ svuint32_t test_svrevd_u32_z(svbool_t pg, svuint32_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv2i64( zeroinitializer, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svuint64_t test_svrevd_u64_z(svbool_t pg, svuint64_t op) { +svuint64_t test_svrevd_u64_z(svbool_t pg, svuint64_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _u64, _z, )(pg, op); } @@ -152,7 +158,7 @@ svuint64_t test_svrevd_u64_z(svbool_t pg, svuint64_t op) { // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.revd.nxv16i8( [[INACTIVE:%.*]], [[PG:%.*]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP0]] // -svint8_t test_svrevd_s8_m(svint8_t inactive, svbool_t pg, svint8_t op) { +svint8_t test_svrevd_s8_m(svint8_t inactive, svbool_t pg, svint8_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _s8, _m, )(inactive, pg, op); } @@ -168,7 +174,7 @@ svint8_t test_svrevd_s8_m(svint8_t inactive, svbool_t pg, svint8_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv8i16( [[INACTIVE:%.*]], [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svint16_t test_svrevd_s16_m(svint16_t inactive, svbool_t pg, svint16_t op) { +svint16_t test_svrevd_s16_m(svint16_t inactive, svbool_t pg, svint16_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _s16, _m, )(inactive, pg, op); } @@ -184,7 +190,7 @@ svint16_t test_svrevd_s16_m(svint16_t inactive, svbool_t pg, svint16_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv4i32( [[INACTIVE:%.*]], [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svint32_t test_svrevd_s32_m(svint32_t inactive, svbool_t pg, svint32_t op) { +svint32_t test_svrevd_s32_m(svint32_t inactive, svbool_t pg, svint32_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _s32, _m, )(inactive, pg, op); } @@ -200,7 +206,7 @@ svint32_t test_svrevd_s32_m(svint32_t inactive, svbool_t pg, svint32_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv2i64( [[INACTIVE:%.*]], [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svint64_t test_svrevd_s64_m(svint64_t inactive, svbool_t pg, svint64_t op) { +svint64_t test_svrevd_s64_m(svint64_t inactive, svbool_t pg, svint64_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _s64, _m, )(inactive, pg, op); } @@ -214,7 +220,7 @@ svint64_t test_svrevd_s64_m(svint64_t inactive, svbool_t pg, svint64_t op) { // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.revd.nxv16i8( [[INACTIVE:%.*]], [[PG:%.*]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP0]] // -svuint8_t test_svrevd_u8_m(svuint8_t inactive, svbool_t pg, svuint8_t op) { +svuint8_t test_svrevd_u8_m(svuint8_t inactive, svbool_t pg, svuint8_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _u8, _m, )(inactive, pg, op); } @@ -230,7 +236,7 @@ svuint8_t test_svrevd_u8_m(svuint8_t inactive, svbool_t pg, svuint8_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv8i16( [[INACTIVE:%.*]], [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svuint16_t test_svrevd_u16_m(svuint16_t inactive, svbool_t pg, svuint16_t op) { +svuint16_t test_svrevd_u16_m(svuint16_t inactive, svbool_t pg, svuint16_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _u16, _m, )(inactive, pg, op); } @@ -246,7 +252,7 @@ svuint16_t test_svrevd_u16_m(svuint16_t inactive, svbool_t pg, svuint16_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv4i32( [[INACTIVE:%.*]], [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svuint32_t test_svrevd_u32_m(svuint32_t inactive, svbool_t pg, svuint32_t op) { +svuint32_t test_svrevd_u32_m(svuint32_t inactive, svbool_t pg, svuint32_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _u32, _m, )(inactive, pg, op); } @@ -262,7 +268,7 @@ svuint32_t test_svrevd_u32_m(svuint32_t inactive, svbool_t pg, svuint32_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv2i64( [[INACTIVE:%.*]], [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svuint64_t test_svrevd_u64_m(svuint64_t inactive, svbool_t pg, svuint64_t op) { +svuint64_t test_svrevd_u64_m(svuint64_t inactive, svbool_t pg, svuint64_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _u64, _m, )(inactive, pg, op); } @@ -276,7 +282,7 @@ svuint64_t test_svrevd_u64_m(svuint64_t inactive, svbool_t pg, svuint64_t op) { // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.revd.nxv16i8( undef, [[PG:%.*]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP0]] // -svint8_t test_svrevd_s8_x(svbool_t pg, svint8_t op) { +svint8_t test_svrevd_s8_x(svbool_t pg, svint8_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _s8, _x, )(pg, op); } @@ -292,7 +298,7 @@ svint8_t test_svrevd_s8_x(svbool_t pg, svint8_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv8i16( undef, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svint16_t test_svrevd_s16_x(svbool_t pg, svint16_t op) { +svint16_t test_svrevd_s16_x(svbool_t pg, svint16_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _s16, _x, )(pg, op); } @@ -308,7 +314,7 @@ svint16_t test_svrevd_s16_x(svbool_t pg, svint16_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv4i32( undef, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svint32_t test_svrevd_s32_x(svbool_t pg, svint32_t op) { +svint32_t test_svrevd_s32_x(svbool_t pg, svint32_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _s32, _x, )(pg, op); } @@ -324,7 +330,7 @@ svint32_t test_svrevd_s32_x(svbool_t pg, svint32_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv2i64( undef, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svint64_t test_svrevd_s64_x(svbool_t pg, svint64_t op) { +svint64_t test_svrevd_s64_x(svbool_t pg, svint64_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _s64, _x, )(pg, op); } @@ -338,7 +344,7 @@ svint64_t test_svrevd_s64_x(svbool_t pg, svint64_t op) { // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.revd.nxv16i8( undef, [[PG:%.*]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP0]] // -svuint8_t test_svrevd_u8_x(svbool_t pg, svuint8_t op) { +svuint8_t test_svrevd_u8_x(svbool_t pg, svuint8_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _u8, _x, )(pg, op); } @@ -354,7 +360,7 @@ svuint8_t test_svrevd_u8_x(svbool_t pg, svuint8_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv8i16( undef, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svuint16_t test_svrevd_u16_x(svbool_t pg, svuint16_t op) { +svuint16_t test_svrevd_u16_x(svbool_t pg, svuint16_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _u16, _x, )(pg, op); } @@ -370,7 +376,7 @@ svuint16_t test_svrevd_u16_x(svbool_t pg, svuint16_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv4i32( undef, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svuint32_t test_svrevd_u32_x(svbool_t pg, svuint32_t op) { +svuint32_t test_svrevd_u32_x(svbool_t pg, svuint32_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _u32, _x, )(pg, op); } @@ -386,7 +392,7 @@ svuint32_t test_svrevd_u32_x(svbool_t pg, svuint32_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv2i64( undef, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svuint64_t test_svrevd_u64_x(svbool_t pg, svuint64_t op) { +svuint64_t test_svrevd_u64_x(svbool_t pg, svuint64_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _u64, _x, )(pg, op); } @@ -403,7 +409,7 @@ svuint64_t test_svrevd_u64_x(svbool_t pg, svuint64_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv8bf16( zeroinitializer, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svrevd_bf16_z(svbool_t pg, svbfloat16_t op) { +svbfloat16_t test_svrevd_bf16_z(svbool_t pg, svbfloat16_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _bf16, _z, )(pg, op); } @@ -419,7 +425,7 @@ svbfloat16_t test_svrevd_bf16_z(svbool_t pg, svbfloat16_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv8f16( zeroinitializer, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svfloat16_t test_svrevd_f16_z(svbool_t pg, svfloat16_t op) { +svfloat16_t test_svrevd_f16_z(svbool_t pg, svfloat16_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _f16, _z, )(pg, op); } @@ -435,7 +441,7 @@ svfloat16_t test_svrevd_f16_z(svbool_t pg, svfloat16_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv4f32( zeroinitializer, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svfloat32_t test_svrevd_f32_z(svbool_t pg, svfloat32_t op) { +svfloat32_t test_svrevd_f32_z(svbool_t pg, svfloat32_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _f32, _z, )(pg, op); } @@ -451,7 +457,7 @@ svfloat32_t test_svrevd_f32_z(svbool_t pg, svfloat32_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv2f64( zeroinitializer, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svfloat64_t test_svrevd_f64_z(svbool_t pg, svfloat64_t op) { +svfloat64_t test_svrevd_f64_z(svbool_t pg, svfloat64_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _f64, _z, )(pg, op); } @@ -467,7 +473,7 @@ svfloat64_t test_svrevd_f64_z(svbool_t pg, svfloat64_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv8bf16( [[INACTIVE:%.*]], [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svrevd_bf16_m(svbfloat16_t inactive, svbool_t pg, svbfloat16_t op) { +svbfloat16_t test_svrevd_bf16_m(svbfloat16_t inactive, svbool_t pg, svbfloat16_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _bf16, _m, )(inactive, pg, op); } @@ -483,7 +489,7 @@ svbfloat16_t test_svrevd_bf16_m(svbfloat16_t inactive, svbool_t pg, svbfloat16_t // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv8f16( [[INACTIVE:%.*]], [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svfloat16_t test_svrevd_f16_m(svfloat16_t inactive, svbool_t pg, svfloat16_t op) { +svfloat16_t test_svrevd_f16_m(svfloat16_t inactive, svbool_t pg, svfloat16_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _f16, _m, )(inactive, pg, op); } @@ -499,7 +505,7 @@ svfloat16_t test_svrevd_f16_m(svfloat16_t inactive, svbool_t pg, svfloat16_t op) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv4f32( [[INACTIVE:%.*]], [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svfloat32_t test_svrevd_f32_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op) { +svfloat32_t test_svrevd_f32_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _f32, _m, )(inactive, pg, op); } @@ -515,7 +521,7 @@ svfloat32_t test_svrevd_f32_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv2f64( [[INACTIVE:%.*]], [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svfloat64_t test_svrevd_f64_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op) { +svfloat64_t test_svrevd_f64_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _f64, _m, )(inactive, pg, op); } @@ -531,7 +537,7 @@ svfloat64_t test_svrevd_f64_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv8bf16( undef, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svrevd_bf16_x(svbool_t pg, svbfloat16_t op) { +svbfloat16_t test_svrevd_bf16_x(svbool_t pg, svbfloat16_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _bf16, _x, )(pg, op); } @@ -547,7 +553,7 @@ svbfloat16_t test_svrevd_bf16_x(svbool_t pg, svbfloat16_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv8f16( undef, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svfloat16_t test_svrevd_f16_x(svbool_t pg, svfloat16_t op) { +svfloat16_t test_svrevd_f16_x(svbool_t pg, svfloat16_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _f16, _x, )(pg, op); } @@ -563,7 +569,7 @@ svfloat16_t test_svrevd_f16_x(svbool_t pg, svfloat16_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv4f32( undef, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svfloat32_t test_svrevd_f32_x(svbool_t pg, svfloat32_t op) { +svfloat32_t test_svrevd_f32_x(svbool_t pg, svfloat32_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _f32, _x, )(pg, op); } @@ -579,6 +585,6 @@ svfloat32_t test_svrevd_f32_x(svbool_t pg, svfloat32_t op) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.revd.nxv2f64( undef, [[TMP0]], [[OP:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svfloat64_t test_svrevd_f64_x(svbool_t pg, svfloat64_t op) { +svfloat64_t test_svrevd_f64_x(svbool_t pg, svfloat64_t op) MODE_ATTR { return SVE_ACLE_FUNC(svrevd, _f64, _x, )(pg, op); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfadd.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfadd.c index 9d01ba773694b2554835cf3103bde78bc5f28d59..d5c24d7c97bda7558aed955aee9d08a6e7bf4819 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfadd.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfadd.c @@ -8,6 +8,12 @@ // RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s #include +#if defined __ARM_FEATURE_SME +#define MODE_ATTR __arm_streaming +#else +#define MODE_ATTR +#endif + #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin. #define SVE_ACLE_FUNC(A1,A2_UNUSED,A3) A1##A3 @@ -27,7 +33,7 @@ // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fadd.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svadd_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svadd_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svadd, _bf16, _m)(pg, op1, op2); } @@ -46,7 +52,7 @@ svbfloat16_t test_svadd_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fadd.nxv8bf16( [[TMP0]], [[TMP1]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svadd_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svadd_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svadd, _bf16, _z)(pg, op1, op2); } @@ -63,7 +69,7 @@ svbfloat16_t test_svadd_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fadd.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svadd_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svadd_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svadd, _bf16, _x)(pg, op1, op2); } @@ -84,7 +90,7 @@ svbfloat16_t test_svadd_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fadd.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svadd_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svadd_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svadd, _n_bf16, _m)(pg, op1, op2); } @@ -107,7 +113,7 @@ svbfloat16_t test_svadd_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fadd.nxv8bf16( [[TMP0]], [[TMP1]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svadd_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svadd_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svadd, _n_bf16, _z)(pg, op1, op2); } @@ -128,7 +134,7 @@ svbfloat16_t test_svadd_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fadd.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svadd_bf16_n_x(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svadd_bf16_n_x(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svadd, _n_bf16, _x)(pg, op1, op2); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmax.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmax.c index ce28a0b0653d7094fb191fb2f37c2ee563b27897..a160e52d662e309cf5cf75c4ed88b3ac66f6b7f5 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmax.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmax.c @@ -8,6 +8,12 @@ // RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s #include +#if defined __ARM_FEATURE_SME +#define MODE_ATTR __arm_streaming +#else +#define MODE_ATTR +#endif + #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin. #define SVE_ACLE_FUNC(A1,A2_UNUSED,A3) A1##A3 @@ -27,7 +33,7 @@ // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmax.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmax_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmax_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmax, _bf16, _m)(pg, op1, op2); } @@ -46,7 +52,7 @@ svbfloat16_t test_svmax_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fmax.nxv8bf16( [[TMP0]], [[TMP1]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svmax_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmax_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmax, _bf16, _z)(pg, op1, op2); } @@ -63,7 +69,7 @@ svbfloat16_t test_svmax_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmax.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmax_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmax_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmax, _bf16, _x)(pg, op1, op2); } @@ -85,7 +91,7 @@ svbfloat16_t test_svmax_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmax.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmax_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmax_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmax, _n_bf16, _m)(pg, op1, op2); } @@ -108,7 +114,7 @@ svbfloat16_t test_svmax_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fmax.nxv8bf16( [[TMP0]], [[TMP1]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svmax_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmax_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmax, _n_bf16, _z)(pg, op1, op2); } @@ -129,7 +135,7 @@ svbfloat16_t test_svmax_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmax.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmax_bf16_n_x(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmax_bf16_n_x(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmax, _n_bf16, _x)(pg, op1, op2); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmaxnm.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmaxnm.c index d8fec8c5145e951810a1467b2823fba9591ff2af..392677c2daa1b215a86ebb62131952efc2869377 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmaxnm.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmaxnm.c @@ -8,6 +8,12 @@ // RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s #include +#if defined __ARM_FEATURE_SME +#define MODE_ATTR __arm_streaming +#else +#define MODE_ATTR +#endif + #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin. #define SVE_ACLE_FUNC(A1,A2_UNUSED,A3) A1##A3 @@ -27,7 +33,7 @@ // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmaxnm.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmaxnm_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmaxnm_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmaxnm, _bf16, _m)(pg, op1, op2); } @@ -46,7 +52,7 @@ svbfloat16_t test_svmaxnm_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2 // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fmaxnm.nxv8bf16( [[TMP0]], [[TMP1]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svmaxnm_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmaxnm_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmaxnm, _bf16, _z)(pg, op1, op2); } @@ -63,7 +69,7 @@ svbfloat16_t test_svmaxnm_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2 // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmaxnm.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmaxnm_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmaxnm_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmaxnm, _bf16, _x)(pg, op1, op2); } @@ -85,7 +91,7 @@ svbfloat16_t test_svmaxnm_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2 // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmaxnm.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmaxnm_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmaxnm_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmaxnm, _n_bf16, _m)(pg, op1, op2); } @@ -108,7 +114,7 @@ svbfloat16_t test_svmaxnm_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2 // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fmaxnm.nxv8bf16( [[TMP0]], [[TMP1]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svmaxnm_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmaxnm_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmaxnm, _n_bf16, _z)(pg, op1, op2); } @@ -129,7 +135,7 @@ svbfloat16_t test_svmaxnm_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2 // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmaxnm.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmaxnm_bf16_n_x(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmaxnm_bf16_n_x(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmaxnm, _n_bf16, _x)(pg, op1, op2); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmin.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmin.c index 5efaa37a14640e4f83281cc515f215ec919f0d2e..5b0e1505c8e984fdc06f104311e279d30b526600 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmin.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmin.c @@ -8,6 +8,12 @@ // RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s #include +#if defined __ARM_FEATURE_SME +#define MODE_ATTR __arm_streaming +#else +#define MODE_ATTR +#endif + #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin. #define SVE_ACLE_FUNC(A1,A2_UNUSED,A3) A1##A3 @@ -27,7 +33,7 @@ // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmin.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmin_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmin_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmin, _bf16, _m)(pg, op1, op2); } @@ -46,7 +52,7 @@ svbfloat16_t test_svmin_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fmin.nxv8bf16( [[TMP0]], [[TMP1]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svmin_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmin_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmin, _bf16, _z)(pg, op1, op2); } @@ -63,7 +69,7 @@ svbfloat16_t test_svmin_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmin.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmin_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmin_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmin, _bf16, _x)(pg, op1, op2); } @@ -85,7 +91,7 @@ svbfloat16_t test_svmin_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmin.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmin_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmin_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmin, _n_bf16, _m)(pg, op1, op2); } @@ -108,7 +114,7 @@ svbfloat16_t test_svmin_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fmin.nxv8bf16( [[TMP0]], [[TMP1]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svmin_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmin_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmin, _n_bf16, _z)(pg, op1, op2); } @@ -129,7 +135,7 @@ svbfloat16_t test_svmin_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmin.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmin_bf16_n_x(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmin_bf16_n_x(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmin, _n_bf16, _x)(pg, op1, op2); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfminnm.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfminnm.c index 98fd12b3a83936538d6b4af95f1220c8674848bf..7a7de42e1419fc85fc7663755ed40e956c002616 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfminnm.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfminnm.c @@ -8,6 +8,12 @@ // RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s #include +#if defined __ARM_FEATURE_SME +#define MODE_ATTR __arm_streaming +#else +#define MODE_ATTR +#endif + #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin. #define SVE_ACLE_FUNC(A1,A2_UNUSED,A3) A1##A3 @@ -27,7 +33,7 @@ // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fminnm.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svminnm_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svminnm_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svminnm, _bf16, _m)(pg, op1, op2); } @@ -46,7 +52,7 @@ svbfloat16_t test_svminnm_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2 // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fminnm.nxv8bf16( [[TMP0]], [[TMP1]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svminnm_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svminnm_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svminnm, _bf16, _z)(pg, op1, op2); } @@ -63,7 +69,7 @@ svbfloat16_t test_svminnm_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2 // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fminnm.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svminnm_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svminnm_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svminnm, _bf16, _x)(pg, op1, op2); } @@ -85,7 +91,7 @@ svbfloat16_t test_svminnm_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2 // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fminnm.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svminnm_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svminnm_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svminnm, _n_bf16, _m)(pg, op1, op2); } @@ -108,7 +114,7 @@ svbfloat16_t test_svminnm_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2 // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fminnm.nxv8bf16( [[TMP0]], [[TMP1]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svminnm_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svminnm_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svminnm, _n_bf16, _z)(pg, op1, op2); } @@ -129,7 +135,7 @@ svbfloat16_t test_svminnm_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2 // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fminnm.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svminnm_bf16_n_x(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svminnm_bf16_n_x(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svminnm, _n_bf16, _x)(pg, op1, op2); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmla.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmla.c index 0a70466a540d2602b1d30c9ae4edaf1ee5c59f56..3663d95b62799cc74a3f00217e6967d6f5a4dfb4 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmla.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmla.c @@ -8,6 +8,12 @@ // RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -o /dev/null %s #include +#if defined __ARM_FEATURE_SME +#define MODE_ATTR __arm_streaming +#else +#define MODE_ATTR +#endif + #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin. #define SVE_ACLE_FUNC(A1,A2_UNUSED,A3) A1##A3 @@ -27,7 +33,7 @@ // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmla.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]], [[OP3:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmla_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, svbfloat16_t op3) __arm_streaming_compatible +svbfloat16_t test_svmla_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, svbfloat16_t op3) MODE_ATTR { return SVE_ACLE_FUNC(svmla, _bf16, _m)(pg, op1, op2, op3); } @@ -46,7 +52,7 @@ svbfloat16_t test_svmla_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fmla.nxv8bf16( [[TMP0]], [[TMP1]], [[OP2:%.*]], [[OP3:%.*]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svmla_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, svbfloat16_t op3) __arm_streaming_compatible +svbfloat16_t test_svmla_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, svbfloat16_t op3) MODE_ATTR { return SVE_ACLE_FUNC(svmla, _bf16, _z)(pg, op1, op2, op3); } @@ -63,7 +69,7 @@ svbfloat16_t test_svmla_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmla.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]], [[OP3:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmla_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, svbfloat16_t op3) __arm_streaming_compatible +svbfloat16_t test_svmla_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, svbfloat16_t op3) MODE_ATTR { return SVE_ACLE_FUNC(svmla, _bf16, _x)(pg, op1, op2, op3); } @@ -84,7 +90,7 @@ svbfloat16_t test_svmla_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmla.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmla_n_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, bfloat16_t op3) __arm_streaming_compatible +svbfloat16_t test_svmla_n_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, bfloat16_t op3) MODE_ATTR { return SVE_ACLE_FUNC(svmla, _n_bf16, _m)(pg, op1, op2, op3); } @@ -107,7 +113,7 @@ svbfloat16_t test_svmla_n_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2 // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fmla.nxv8bf16( [[TMP0]], [[TMP1]], [[OP2:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svmla_n_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, bfloat16_t op3) __arm_streaming_compatible +svbfloat16_t test_svmla_n_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, bfloat16_t op3) MODE_ATTR { return SVE_ACLE_FUNC(svmla, _n_bf16, _z)(pg, op1, op2, op3); } @@ -128,7 +134,7 @@ svbfloat16_t test_svmla_n_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2 // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmla.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmla_n_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, bfloat16_t op3) __arm_streaming_compatible +svbfloat16_t test_svmla_n_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, bfloat16_t op3) MODE_ATTR { return SVE_ACLE_FUNC(svmla, _n_bf16, _x)(pg, op1, op2, op3); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmls.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmls.c index ed71d4e490bb34b15e3e5085276455b3e0c946ee..73619e10dfededd7ea1504cada95e1df72808646 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmls.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmls.c @@ -8,6 +8,12 @@ // RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -o /dev/null %s #include +#if defined __ARM_FEATURE_SME +#define MODE_ATTR __arm_streaming +#else +#define MODE_ATTR +#endif + #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin. #define SVE_ACLE_FUNC(A1,A2_UNUSED,A3) A1##A3 @@ -27,7 +33,7 @@ // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmls.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]], [[OP3:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmls_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, svbfloat16_t op3) __arm_streaming_compatible +svbfloat16_t test_svmls_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, svbfloat16_t op3) MODE_ATTR { return SVE_ACLE_FUNC(svmls, _bf16, _m)(pg, op1, op2, op3); } @@ -46,7 +52,7 @@ svbfloat16_t test_svmls_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fmls.nxv8bf16( [[TMP0]], [[TMP1]], [[OP2:%.*]], [[OP3:%.*]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svmls_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, svbfloat16_t op3) __arm_streaming_compatible +svbfloat16_t test_svmls_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, svbfloat16_t op3) MODE_ATTR { return SVE_ACLE_FUNC(svmls, _bf16, _z)(pg, op1, op2, op3); } @@ -63,7 +69,7 @@ svbfloat16_t test_svmls_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmls.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]], [[OP3:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmls_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, svbfloat16_t op3) __arm_streaming_compatible +svbfloat16_t test_svmls_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, svbfloat16_t op3) MODE_ATTR { return SVE_ACLE_FUNC(svmls, _bf16, _x)(pg, op1, op2, op3); } @@ -84,7 +90,7 @@ svbfloat16_t test_svmls_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmls.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmls_n_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, bfloat16_t op3) __arm_streaming_compatible +svbfloat16_t test_svmls_n_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, bfloat16_t op3) MODE_ATTR { return SVE_ACLE_FUNC(svmls, _n_bf16, _m)(pg, op1, op2, op3); } @@ -107,7 +113,7 @@ svbfloat16_t test_svmls_n_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2 // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fmls.nxv8bf16( [[TMP0]], [[TMP1]], [[OP2:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svmls_n_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, bfloat16_t op3) __arm_streaming_compatible +svbfloat16_t test_svmls_n_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, bfloat16_t op3) MODE_ATTR { return SVE_ACLE_FUNC(svmls, _n_bf16, _z)(pg, op1, op2, op3); } @@ -128,7 +134,7 @@ svbfloat16_t test_svmls_n_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2 // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmls.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmls_n_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, bfloat16_t op3) __arm_streaming_compatible +svbfloat16_t test_svmls_n_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2, bfloat16_t op3) MODE_ATTR { return SVE_ACLE_FUNC(svmls, _n_bf16, _x)(pg, op1, op2, op3); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmul.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmul.c index f0a3664426de82d0b2e74ed4f89d60a3a3b3f0a1..f5e96996c3600ee596b9ffe8cb3490a41b12c378 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmul.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmul.c @@ -8,6 +8,12 @@ // RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s #include +#if defined __ARM_FEATURE_SME +#define MODE_ATTR __arm_streaming +#else +#define MODE_ATTR +#endif + #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin. #define SVE_ACLE_FUNC(A1,A2_UNUSED,A3) A1##A3 @@ -27,7 +33,7 @@ // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmul.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmul_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmul_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmul, _bf16, _m)(pg, op1, op2); } @@ -46,7 +52,7 @@ svbfloat16_t test_svmul_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fmul.nxv8bf16( [[TMP0]], [[TMP1]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svmul_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmul_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmul, _bf16, _z)(pg, op1, op2); } @@ -63,7 +69,7 @@ svbfloat16_t test_svmul_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmul.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmul_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmul_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmul, _bf16, _x)(pg, op1, op2); } @@ -85,7 +91,7 @@ svbfloat16_t test_svmul_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmul.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmul_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmul_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmul, _n_bf16, _m)(pg, op1, op2); } @@ -108,7 +114,7 @@ svbfloat16_t test_svmul_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fmul.nxv8bf16( [[TMP0]], [[TMP1]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svmul_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmul_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmul, _n_bf16, _z)(pg, op1, op2); } @@ -129,7 +135,7 @@ svbfloat16_t test_svmul_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fmul.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svmul_bf16_n_x(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svmul_bf16_n_x(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svmul, _n_bf16, _x)(pg, op1, op2); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfsub.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfsub.c index 6f08ea84ab8234c0c65149e06e926841c4da9dc8..464eeac67e519e5672ca249726e28a9ad245e2ae 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfsub.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfsub.c @@ -8,6 +8,12 @@ // RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s #include +#if defined __ARM_FEATURE_SME +#define MODE_ATTR __arm_streaming +#else +#define MODE_ATTR +#endif + #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin. #define SVE_ACLE_FUNC(A1,A2_UNUSED,A3) A1##A3 @@ -27,7 +33,7 @@ // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fsub.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svsub_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svsub_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svsub, _bf16, _m)(pg, op1, op2); } @@ -46,7 +52,7 @@ svbfloat16_t test_svsub_bf16_m(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fsub.nxv8bf16( [[TMP0]], [[TMP1]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svsub_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svsub_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svsub, _bf16, _z)(pg, op1, op2); } @@ -63,7 +69,7 @@ svbfloat16_t test_svsub_bf16_z(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fsub.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[OP2:%.*]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svsub_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svsub_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svsub, _bf16, _x)(pg, op1, op2); } @@ -85,7 +91,7 @@ svbfloat16_t test_svsub_bf16_x(svbool_t pg, svbfloat16_t op1, svbfloat16_t op2) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fsub.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svsub_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svsub_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svsub, _n_bf16, _m)(pg, op1, op2); } @@ -108,7 +114,7 @@ svbfloat16_t test_svsub_bf16_n_m(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fsub.nxv8bf16( [[TMP0]], [[TMP1]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP2]] // -svbfloat16_t test_svsub_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svsub_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svsub, _n_bf16, _z)(pg, op1, op2); } @@ -129,7 +135,7 @@ svbfloat16_t test_svsub_bf16_n_z(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.fsub.u.nxv8bf16( [[TMP0]], [[OP1:%.*]], [[DOTSPLAT]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbfloat16_t test_svsub_bf16_n_x(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) __arm_streaming_compatible +svbfloat16_t test_svsub_bf16_n_x(svbool_t pg, svbfloat16_t op1, bfloat16_t op2) MODE_ATTR { return SVE_ACLE_FUNC(svsub, _n_bf16, _x)(pg, op1, op2); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_create2_bool.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_create2_bool.c index d441c934bad08a277c50623a863b573e842d5f16..3728053b26e113fe3356894077b5473dfe0f4847 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_create2_bool.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_create2_bool.c @@ -5,19 +5,25 @@ // RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK // RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve2p1 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ // RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -DTEST_SME2 -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ // RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s // RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve2p1 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s\ // RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -DTEST_SME -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s \ +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s \ // RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK // RUN: %clang_cc1 -triple aarch64 -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s -// RUN: %clang_cc1 -DTEST_SME2 -triple aarch64 -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s // REQUIRES: aarch64-registered-target #include +#if defined __ARM_FEATURE_SME +#define MODE_ATTR __arm_streaming +#else +#define MODE_ATTR +#endif + #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin. #define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 @@ -25,12 +31,6 @@ #define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 #endif -#ifndef TEST_SME2 -#define ATTR -#else -#define ATTR __arm_streaming -#endif - // CHECK-LABEL: @test_svcreate2_b( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[X0:%.*]], i64 0) @@ -43,7 +43,7 @@ // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP0]], [[X1:%.*]], i64 16) // CPP-CHECK-NEXT: ret [[TMP1]] // -svboolx2_t test_svcreate2_b(svbool_t x0, svbool_t x1) ATTR +svboolx2_t test_svcreate2_b(svbool_t x0, svbool_t x1) MODE_ATTR { return SVE_ACLE_FUNC(svcreate2,_b,,)(x0, x1); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_get4_bool.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_get4_bool.c index e5016d6cb3dc85a52098b7b37e81765998c859ad..0b2a382d71bd3137b2f6f3d8b771bff94642af08 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_get4_bool.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_get4_bool.c @@ -5,19 +5,25 @@ // RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK // RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve2p1 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ // RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -DTEST_SME2 -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ // RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s // RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve2p1 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s\ // RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -DTEST_SME2 -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s \ +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s \ // RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK // RUN: %clang_cc1 -triple aarch64 -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s -// RUN: %clang_cc1 -DTEST_SME2 -triple aarch64 -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s // REQUIRES: aarch64-registered-target #include +#if defined __ARM_FEATURE_SME +#define MODE_ATTR __arm_streaming +#else +#define MODE_ATTR +#endif + #ifdef SVE_OVERLOADED_FORMS // A simple used,unused... macro, long enough to represent any SVE builtin. #define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 @@ -25,12 +31,6 @@ #define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 #endif -#ifndef TEST_SME -#define ATTR -#else -#define ATTR __arm_streaming -#endif - // NOTE: For these tests clang converts the struct parameter into // several parameters, one for each member of the original struct. // CHECK-LABEL: @test_svget4_b_0( @@ -43,7 +43,7 @@ // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i1.nxv64i1( [[TUPLE:%.*]], i64 0) // CPP-CHECK-NEXT: ret [[TMP0]] // -svbool_t test_svget4_b_0(svboolx4_t tuple) ATTR +svbool_t test_svget4_b_0(svboolx4_t tuple) MODE_ATTR { return SVE_ACLE_FUNC(svget4,_b,,)(tuple, 0); } @@ -60,7 +60,7 @@ svbool_t test_svget4_b_0(svboolx4_t tuple) ATTR // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i1.nxv64i1( [[TUPLE:%.*]], i64 16) // CPP-CHECK-NEXT: ret [[TMP0]] // -svbool_t test_svget4_b_1(svboolx4_t tuple) ATTR +svbool_t test_svget4_b_1(svboolx4_t tuple) MODE_ATTR { return SVE_ACLE_FUNC(svget4,_b,,)(tuple, 1); } @@ -77,7 +77,7 @@ svbool_t test_svget4_b_1(svboolx4_t tuple) ATTR // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i1.nxv64i1( [[TUPLE:%.*]], i64 48) // CPP-CHECK-NEXT: ret [[TMP0]] // -svbool_t test_svget4_b_3(svboolx4_t tuple) ATTR +svbool_t test_svget4_b_3(svboolx4_t tuple) MODE_ATTR { return SVE_ACLE_FUNC(svget4,_b,,)(tuple, 3); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_undef_bool.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_undef_bool.c index 5197e41c1ffdd7ac0592a82e3fa6a7731856daf9..16ba689964a3fec89994768f71242a632185a9c2 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_undef_bool.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_undef_bool.c @@ -9,6 +9,12 @@ #include +#if defined __ARM_FEATURE_SME +#define MODE_ATTR __arm_streaming +#else +#define MODE_ATTR +#endif + // CHECK-LABEL: define dso_local @test_svundef2_b( // CPP-CHECK-LABEL: define dso_local @_Z15test_svundef2_bv( // @@ -18,7 +24,7 @@ // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: ret undef // -svboolx2_t test_svundef2_b() { +svboolx2_t test_svundef2_b(void) MODE_ATTR { return svundef2_b(); } @@ -31,6 +37,6 @@ svboolx2_t test_svundef2_b() { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: ret undef // -svboolx4_t test_svundef4_b() { +svboolx4_t test_svundef4_b(void) MODE_ATTR { return svundef4_b(); } diff --git a/clang/test/CodeGen/array-init.c b/clang/test/CodeGen/array-init.c index 62e87edc29741977982ae91ab988c96e72824046..b3accf4829949af23d8de172c5805293c8125a1b 100644 --- a/clang/test/CodeGen/array-init.c +++ b/clang/test/CodeGen/array-init.c @@ -13,3 +13,13 @@ void testConstArrayInits(void) const int a2[5] = {0,0,0}; const int a3[5] = {0}; } + +/// https://github.com/llvm/llvm-project/issues/57353 +// CHECK: @big_char ={{.*}} global <{ i8, [4294967295 x i8] }> <{ i8 1, [4294967295 x i8] zeroinitializer }> +char big_char[4294967296] = {1}; + +// CHECK: @big_char2 ={{.*}} global <{ i8, i8, [4294967296 x i8] }> <{ i8 1, i8 2, [4294967296 x i8] zeroinitializer }> +char big_char2[4294967298] = {1, 2}; + +// CHECK: @big_int ={{.*}} global <{ i32, i32, i32, [2147483647 x i32] }> <{ i32 1, i32 2, i32 3, [2147483645 x i32] zeroinitializer }> +int big_int[0x200000000 >> 2] = {1, 2, 3}; diff --git a/clang/test/CodeGen/attr-counted-by.c b/clang/test/CodeGen/attr-counted-by.c index de30a00138ac8042ae06771eb6875d4ce767ff5f..79922eb4159f1c38888781e7ef480521a4c20328 100644 --- a/clang/test/CodeGen/attr-counted-by.c +++ b/clang/test/CodeGen/attr-counted-by.c @@ -1098,7 +1098,7 @@ int test12_a, test12_b; // SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB20:[0-9]+]], i64 0) #[[ATTR10]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.type_mismatch6: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB21:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0) to i64)) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB21:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @test12_foo, i64 4) to i64)) #[[ATTR10]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i32 @test12( @@ -1111,7 +1111,7 @@ int test12_a, test12_b; // NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[IDXPROM]] // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP0]], ptr @test12_b, align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0), align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds (i8, ptr @test12_foo, i64 4), align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP1]], ptr @test12_a, align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITH-ATTR-NEXT: br label [[FOR_COND:%.*]] // NO-SANITIZE-WITH-ATTR: for.cond: @@ -1140,7 +1140,7 @@ int test12_a, test12_b; // SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 0) #[[ATTR8]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR: handler.type_mismatch6: -// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0) to i64)) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @test12_foo, i64 4) to i64)) #[[ATTR8]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] // // NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i32 @test12( @@ -1153,7 +1153,7 @@ int test12_a, test12_b; // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[IDXPROM]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[TMP0]], ptr @test12_b, align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0), align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds (i8, ptr @test12_foo, i64 4), align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[TMP1]], ptr @test12_a, align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: br label [[FOR_COND:%.*]] // NO-SANITIZE-WITHOUT-ATTR: for.cond: @@ -1315,7 +1315,7 @@ int test14(int idx) { // NO-SANITIZE-WITH-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR4]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: // NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr getelementptr inbounds ([[STRUCT_ANON_8:%.*]], ptr @__const.test15.foo, i64 1, i32 0), i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr getelementptr inbounds (i8, ptr @__const.test15.foo, i64 8), i64 0, i64 [[IDXPROM]] // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP0]] // @@ -1336,7 +1336,7 @@ int test14(int idx) { // NO-SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR1]] { // NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr getelementptr inbounds ([[STRUCT_ANON_8:%.*]], ptr @__const.test15.foo, i64 1, i32 0), i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr getelementptr inbounds (i8, ptr @__const.test15.foo, i64 8), i64 0, i64 [[IDXPROM]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP0]] // diff --git a/clang/test/CodeGen/clspv_libclc_builtin.c b/clang/test/CodeGen/clspv_libclc_builtin.c new file mode 100644 index 0000000000000000000000000000000000000000..ada2555c79e5bcafa3a84730374bdecd5b47d8fd --- /dev/null +++ b/clang/test/CodeGen/clspv_libclc_builtin.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -triple spir -emit-llvm %s -o - | FileCheck %s + +// CHECK: @foo() +// CHECK-SAME: !clspv_libclc_builtin + +void __attribute__((clspv_libclc_builtin)) foo() {} diff --git a/clang/test/CodeGenCXX/atomicinit.cpp b/clang/test/CodeGenCXX/atomicinit.cpp index f2398b020621f04db086d7a0a575fddbade58566..a568f17b90d0c7fccb135212e60f06b743316797 100644 --- a/clang/test/CodeGenCXX/atomicinit.cpp +++ b/clang/test/CodeGenCXX/atomicinit.cpp @@ -86,7 +86,7 @@ namespace PR18097 { }; // CHECK-LABEL: define {{.*}} @__cxx_global_var_init // CHECK: call void @_ZN7PR180977dynamic1XC1Ei(ptr {{[^,]*}} @_ZN7PR180977dynamic1yE, i32 noundef 4) - // CHECK: store i32 5, ptr getelementptr inbounds ({{.*}}, ptr @_ZN7PR180977dynamic1yE, i32 0, i32 1) + // CHECK: store i32 5, ptr getelementptr inbounds (i8, ptr @_ZN7PR180977dynamic1yE, i32 4) Y y = { X(4), 5 }; } @@ -110,7 +110,7 @@ namespace PR18097 { // CHECK-LABEL: define {{.*}} @__cxx_global_var_init // CHECK: tail call void @llvm.memcpy.p0.p0.i32(ptr{{.*}} @_ZN7PR180978constant2y2E, ptr{{.*}} @_ZN7PR180978constantL1xE, i32 3, i1 false) // CHECK: %0 = load i32, ptr @_ZN7PR180978constant1zE - // CHECK: store i32 %0, ptr getelementptr inbounds (%"struct.PR18097::constant::Y", ptr @_ZN7PR180978constant2y2E, i32 0, i32 1) + // CHECK: store i32 %0, ptr getelementptr inbounds (i8, ptr @_ZN7PR180978constant2y2E, i32 4) int z; constexpr X x{1}; Y y2 = { x, z }; diff --git a/clang/test/CodeGenCXX/auto-var-init.cpp b/clang/test/CodeGenCXX/auto-var-init.cpp index 7803ed5b633fede5beebe41359e08fd188919bd2..e1568bee136e5e03a5152828afc8af7159d768b7 100644 --- a/clang/test/CodeGenCXX/auto-var-init.cpp +++ b/clang/test/CodeGenCXX/auto-var-init.cpp @@ -1346,7 +1346,7 @@ TEST_UNINIT(base, base); // PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_base_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_base_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV4base, i64 0, i32 0, i64 2), {{.*}}, align 8 +// ZERO-O1: store ptr getelementptr inbounds inrange(-16, 16) (i8, ptr @_ZTV4base, i64 16), {{.*}}, align 8 // ZERO-O1-NOT: !annotation TEST_BRACES(base, base); @@ -1367,7 +1367,7 @@ TEST_UNINIT(derived, derived); // ZERO-LABEL: @test_derived_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.+}}), !annotation [[AUTO_INIT]] // ZERO-O1: store i64 0, {{.*}} align 8, !annotation [[AUTO_INIT]] -// ZERO-O1: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV7derived, i64 0, i32 0, i64 2), {{.*}} align 8 +// ZERO-O1: store ptr getelementptr inbounds inrange(-16, 16) (i8, ptr @_ZTV7derived, i64 16), {{.*}} align 8 TEST_BRACES(derived, derived); // CHECK-LABEL: @test_derived_braces() diff --git a/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp b/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp index 83a408984b7605d572c1e9c543cd3b9d72d66589..3d5e32516c7af2fe5075b790fd68115e76cd873c 100644 --- a/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp +++ b/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp @@ -1,24 +1,127 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --no-generate-body-for-unused-prefixes --version 4 // RUN: %clang_cc1 -I%S %s -triple amdgcn-amd-amdhsa -emit-llvm -fcxx-exceptions -fexceptions -o - | FileCheck %s +// RUN: %clang_cc1 -I%S %s -triple spirv64-unknown-unknown -fsycl-is-device -emit-llvm -fcxx-exceptions -fexceptions -o - | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS + struct A { virtual void f(); }; struct B : A { }; -// CHECK: {{define.*@_Z1fP1A}} -// CHECK-SAME: personality ptr @__gxx_personality_v0 B fail; +//. +// CHECK: @_ZTV1B = linkonce_odr unnamed_addr addrspace(1) constant { [3 x ptr addrspace(1)] } { [3 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) @_ZTI1B, ptr addrspace(1) addrspacecast (ptr @_ZN1A1fEv to ptr addrspace(1))] }, comdat, align 8 +// CHECK: @fail = addrspace(1) global { ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2) }, align 8 +// CHECK: @_ZTI1A = external addrspace(1) constant ptr addrspace(1) +// CHECK: @_ZTVN10__cxxabiv120__si_class_type_infoE = external addrspace(1) global [0 x ptr addrspace(1)] +// CHECK: @_ZTS1B = linkonce_odr addrspace(1) constant [3 x i8] c"1B\00", comdat, align 1 +// CHECK: @_ZTI1B = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1B, ptr addrspace(1) @_ZTI1A }, comdat, align 8 +// CHECK: @__oclc_ABI_version = weak_odr hidden local_unnamed_addr addrspace(4) constant i32 500 +//. +// WITH-NONZERO-DEFAULT-AS: @_ZTV1B = linkonce_odr unnamed_addr addrspace(1) constant { [3 x ptr addrspace(1)] } { [3 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) @_ZTI1B, ptr addrspace(1) addrspacecast (ptr @_ZN1A1fEv to ptr addrspace(1))] }, comdat, align 8 +// WITH-NONZERO-DEFAULT-AS: @fail = addrspace(1) global { ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2) }, align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZTI1A = external addrspace(1) constant ptr addrspace(1) +// WITH-NONZERO-DEFAULT-AS: @_ZTVN10__cxxabiv120__si_class_type_infoE = external addrspace(1) global [0 x ptr addrspace(1)] +// WITH-NONZERO-DEFAULT-AS: @_ZTS1B = linkonce_odr addrspace(1) constant [3 x i8] c"1B\00", comdat, align 1 +// WITH-NONZERO-DEFAULT-AS: @_ZTI1B = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1B, ptr addrspace(1) @_ZTI1A }, comdat, align 8 +//. +// CHECK-LABEL: define dso_local noundef nonnull align 8 dereferenceable(8) ptr @_Z1fP1A( +// CHECK-SAME: ptr noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] personality ptr @__gxx_personality_v0 { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca ptr, align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) +// CHECK-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 8, addrspace(5) +// CHECK-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4, addrspace(5) +// CHECK-NEXT: [[RETVAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[RETVAL]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = call ptr @__dynamic_cast(ptr [[TMP0]], ptr addrspace(1) @_ZTI1A, ptr addrspace(1) @_ZTI1B, i64 0) #[[ATTR3:[0-9]+]] +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP1]], null +// CHECK-NEXT: br i1 [[TMP2]], label [[DYNAMIC_CAST_BAD_CAST:%.*]], label [[DYNAMIC_CAST_END:%.*]] +// CHECK: dynamic_cast.bad_cast: +// CHECK-NEXT: invoke void @__cxa_bad_cast() #[[ATTR4:[0-9]+]] +// CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] +// CHECK: invoke.cont: +// CHECK-NEXT: unreachable +// CHECK: dynamic_cast.end: +// CHECK-NEXT: br label [[TRY_CONT:%.*]] +// CHECK: lpad: +// CHECK-NEXT: [[TMP3:%.*]] = landingpad { ptr, i32 } +// CHECK-NEXT: catch ptr null +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { ptr, i32 } [[TMP3]], 0 +// CHECK-NEXT: store ptr [[TMP4]], ptr addrspace(5) [[EXN_SLOT]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP3]], 1 +// CHECK-NEXT: store i32 [[TMP5]], ptr addrspace(5) [[EHSELECTOR_SLOT]], align 4 +// CHECK-NEXT: br label [[CATCH:%.*]] +// CHECK: catch: +// CHECK-NEXT: [[EXN:%.*]] = load ptr, ptr addrspace(5) [[EXN_SLOT]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]]) #[[ATTR3]] +// CHECK-NEXT: call void @__cxa_end_catch() +// CHECK-NEXT: br label [[TRY_CONT]] +// CHECK: try.cont: +// CHECK-NEXT: ret ptr addrspacecast (ptr addrspace(1) @fail to ptr) +// +// WITH-NONZERO-DEFAULT-AS-LABEL: define spir_func noundef align 8 dereferenceable(8) ptr addrspace(4) @_Z1fP1A( +// WITH-NONZERO-DEFAULT-AS-SAME: ptr addrspace(4) noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] personality ptr @__gxx_personality_v0 { +// WITH-NONZERO-DEFAULT-AS-NEXT: entry: +// WITH-NONZERO-DEFAULT-AS-NEXT: [[RETVAL:%.*]] = alloca ptr addrspace(4), align 8 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[A_ADDR:%.*]] = alloca ptr addrspace(4), align 8 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[EXN_SLOT:%.*]] = alloca ptr addrspace(4), align 8 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[RETVAL_ASCAST:%.*]] = addrspacecast ptr [[RETVAL]] to ptr addrspace(4) +// WITH-NONZERO-DEFAULT-AS-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr [[A_ADDR]] to ptr addrspace(4) +// WITH-NONZERO-DEFAULT-AS-NEXT: store ptr addrspace(4) [[A]], ptr addrspace(4) [[A_ADDR_ASCAST]], align 8 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[TMP0:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[A_ADDR_ASCAST]], align 8 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[TMP1:%.*]] = call spir_func ptr addrspace(4) @__dynamic_cast(ptr addrspace(4) [[TMP0]], ptr addrspace(1) @_ZTI1A, ptr addrspace(1) @_ZTI1B, i64 0) #[[ATTR3:[0-9]+]] +// WITH-NONZERO-DEFAULT-AS-NEXT: [[TMP2:%.*]] = icmp eq ptr addrspace(4) [[TMP1]], null +// WITH-NONZERO-DEFAULT-AS-NEXT: br i1 [[TMP2]], label [[DYNAMIC_CAST_BAD_CAST:%.*]], label [[DYNAMIC_CAST_END:%.*]] +// WITH-NONZERO-DEFAULT-AS: dynamic_cast.bad_cast: +// WITH-NONZERO-DEFAULT-AS-NEXT: invoke spir_func void @__cxa_bad_cast() #[[ATTR4:[0-9]+]] +// WITH-NONZERO-DEFAULT-AS-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] +// WITH-NONZERO-DEFAULT-AS: invoke.cont: +// WITH-NONZERO-DEFAULT-AS-NEXT: unreachable +// WITH-NONZERO-DEFAULT-AS: dynamic_cast.end: +// WITH-NONZERO-DEFAULT-AS-NEXT: br label [[TRY_CONT:%.*]] +// WITH-NONZERO-DEFAULT-AS: lpad: +// WITH-NONZERO-DEFAULT-AS-NEXT: [[TMP3:%.*]] = landingpad { ptr addrspace(4), i32 } +// WITH-NONZERO-DEFAULT-AS-NEXT: catch ptr addrspace(4) null +// WITH-NONZERO-DEFAULT-AS-NEXT: [[TMP4:%.*]] = extractvalue { ptr addrspace(4), i32 } [[TMP3]], 0 +// WITH-NONZERO-DEFAULT-AS-NEXT: store ptr addrspace(4) [[TMP4]], ptr [[EXN_SLOT]], align 8 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[TMP5:%.*]] = extractvalue { ptr addrspace(4), i32 } [[TMP3]], 1 +// WITH-NONZERO-DEFAULT-AS-NEXT: store i32 [[TMP5]], ptr [[EHSELECTOR_SLOT]], align 4 +// WITH-NONZERO-DEFAULT-AS-NEXT: br label [[CATCH:%.*]] +// WITH-NONZERO-DEFAULT-AS: catch: +// WITH-NONZERO-DEFAULT-AS-NEXT: [[EXN:%.*]] = load ptr addrspace(4), ptr [[EXN_SLOT]], align 8 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[TMP6:%.*]] = call spir_func ptr addrspace(4) @__cxa_begin_catch(ptr addrspace(4) [[EXN]]) #[[ATTR3]] +// WITH-NONZERO-DEFAULT-AS-NEXT: call spir_func void @__cxa_end_catch() +// WITH-NONZERO-DEFAULT-AS-NEXT: br label [[TRY_CONT]] +// WITH-NONZERO-DEFAULT-AS: try.cont: +// WITH-NONZERO-DEFAULT-AS-NEXT: ret ptr addrspace(4) addrspacecast (ptr addrspace(1) @fail to ptr addrspace(4)) +// const B& f(A *a) { try { - // CHECK: call ptr @__dynamic_cast - // CHECK: br i1 - // CHECK: invoke void @__cxa_bad_cast() [[NR:#[0-9]+]] dynamic_cast(*a); } catch (...) { - // CHECK: landingpad { ptr, i32 } - // CHECK-NEXT: catch ptr null } return fail; } -// CHECK: declare ptr @__dynamic_cast(ptr, ptr addrspace(1), ptr addrspace(1), i64) [[NUW_RO:#[0-9]+]] -// CHECK: attributes [[NUW_RO]] = { nounwind willreturn memory(read) } -// CHECK: attributes [[NR]] = { noreturn } +//. +// CHECK: attributes #[[ATTR0]] = { mustprogress noinline optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +// CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind willreturn memory(read) } +// CHECK: attributes #[[ATTR2:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +// CHECK: attributes #[[ATTR3]] = { nounwind } +// CHECK: attributes #[[ATTR4]] = { noreturn } +//. +// WITH-NONZERO-DEFAULT-AS: attributes #[[ATTR0]] = { convergent mustprogress noinline norecurse nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +// WITH-NONZERO-DEFAULT-AS: attributes #[[ATTR1:[0-9]+]] = { nounwind willreturn memory(read) } +// WITH-NONZERO-DEFAULT-AS: attributes #[[ATTR2:[0-9]+]] = { convergent nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +// WITH-NONZERO-DEFAULT-AS: attributes #[[ATTR3]] = { nounwind } +// WITH-NONZERO-DEFAULT-AS: attributes #[[ATTR4]] = { noreturn } +//. +// CHECK: [[META0:![0-9]+]] = !{i32 1, !"amdhsa_code_object_version", i32 500} +// CHECK: [[META1:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} +// CHECK: [[META2:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} +//. +// WITH-NONZERO-DEFAULT-AS: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} +// WITH-NONZERO-DEFAULT-AS: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} +//. diff --git a/clang/test/CodeGenCXX/eh.cpp b/clang/test/CodeGenCXX/eh.cpp index 5c592a96e27b737c848f4a8578fcefb4e567e3cf..f174b5d84fdf50619d2b811605bdc9256b95aba2 100644 --- a/clang/test/CodeGenCXX/eh.cpp +++ b/clang/test/CodeGenCXX/eh.cpp @@ -81,7 +81,7 @@ namespace test5 { // CHECK: invoke void @__cxa_throw(ptr [[EXNOBJ]], ptr @_ZTIN5test51AE, ptr @_ZN5test51AD1Ev) [[NR]] // CHECK-NEXT: to label {{%.*}} unwind label %[[HANDLER:[^ ]*]] // : [[HANDLER]]: (can't check this in Release-Asserts builds) -// CHECK: {{%.*}} = call i32 @llvm.eh.typeid.for(ptr @_ZTIN5test51AE) +// CHECK: {{%.*}} = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIN5test51AE) } namespace test6 { @@ -96,7 +96,7 @@ namespace test6 { // PR7127 namespace test7 { -// CHECK-LABEL: define{{.*}} i32 @_ZN5test73fooEv() +// CHECK-LABEL: define{{.*}} i32 @_ZN5test73fooEv() // CHECK-SAME: personality ptr @__gxx_personality_v0 int foo() { // CHECK: [[CAUGHTEXNVAR:%.*]] = alloca ptr @@ -119,7 +119,7 @@ namespace test7 { // CHECK-NEXT: store i32 [[SELECTOR]], ptr [[SELECTORVAR]] // CHECK-NEXT: br label // CHECK: [[SELECTOR:%.*]] = load i32, ptr [[SELECTORVAR]] -// CHECK-NEXT: [[T0:%.*]] = call i32 @llvm.eh.typeid.for(ptr @_ZTIi) +// CHECK-NEXT: [[T0:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) // CHECK-NEXT: icmp eq i32 [[SELECTOR]], [[T0]] // CHECK-NEXT: br i1 // CHECK: [[T0:%.*]] = load ptr, ptr [[CAUGHTEXNVAR]] diff --git a/clang/test/CodeGenCXX/nrvo.cpp b/clang/test/CodeGenCXX/nrvo.cpp index 33dc4cf9dbc8d25893a67fa9eaf7576203fd2472..23ac04511514dab1ae42341de895c04a55f20df2 100644 --- a/clang/test/CodeGenCXX/nrvo.cpp +++ b/clang/test/CodeGenCXX/nrvo.cpp @@ -628,7 +628,7 @@ void may_throw(); // CHECK-EH-03-NEXT: br label [[CATCH_DISPATCH:%.*]] // CHECK-EH-03: catch.dispatch: // CHECK-EH-03-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 -// CHECK-EH-03-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for(ptr @_ZTI1X) #[[ATTR7]] +// CHECK-EH-03-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTI1X) #[[ATTR7]] // CHECK-EH-03-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]] // CHECK-EH-03-NEXT: br i1 [[MATCHES]], label [[CATCH:%.*]], label [[EH_RESUME:%.*]] // CHECK-EH-03: catch: @@ -707,7 +707,7 @@ void may_throw(); // CHECK-EH-11-NEXT: br label [[CATCH_DISPATCH:%.*]] // CHECK-EH-11: catch.dispatch: // CHECK-EH-11-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 -// CHECK-EH-11-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for(ptr @_ZTI1X) #[[ATTR6]] +// CHECK-EH-11-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTI1X) #[[ATTR6]] // CHECK-EH-11-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]] // CHECK-EH-11-NEXT: br i1 [[MATCHES]], label [[CATCH:%.*]], label [[EH_RESUME:%.*]] // CHECK-EH-11: catch: diff --git a/clang/test/CodeGenCXX/template-param-objects-address-space.cpp b/clang/test/CodeGenCXX/template-param-objects-address-space.cpp index b54dcfe77934ee23a0738e7900b9fea270a049e6..b3733decdb550fbaf60dc7ece603488cd2797873 100644 --- a/clang/test/CodeGenCXX/template-param-objects-address-space.cpp +++ b/clang/test/CodeGenCXX/template-param-objects-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -std=c++20 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple spirv64-unknown-unknown -fsycl-is-device -std=c++20 %s -emit-llvm -o - | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS struct S { char buf[32]; }; template constexpr const char *begin() { return s.buf; } @@ -8,25 +9,34 @@ extern const void *callee(const S*); template constexpr const void* observable_addr() { return callee(&s); } // CHECK: [[HELLO:@_ZTAXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEE]] +// WITH-NONZERO-DEFAULT-AS: [[HELLO:@_ZTAXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEE]] // CHECK-SAME: = linkonce_odr addrspace(1) constant { <{ [11 x i8], [21 x i8] }> } { <{ [11 x i8], [21 x i8] }> <{ [11 x i8] c"hello world", [21 x i8] zeroinitializer }> }, comdat // CHECK: @p // CHECK-SAME: addrspace(1) global ptr addrspacecast (ptr addrspace(1) [[HELLO]] to ptr) +// WITH-NONZERO-DEFAULT-AS: addrspace(1) global ptr addrspace(4) addrspacecast (ptr addrspace(1) [[HELLO]] to ptr addrspace(4)) const char *p = begin(); // CHECK: @q // CHECK-SAME: addrspace(1) global ptr addrspacecast (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) [[HELLO]], i64 11) to ptr) +// WITH-NONZERO-DEFAULT-AS: addrspace(1) global ptr addrspace(4) addrspacecast (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) [[HELLO]], i64 11) to ptr addrspace(4)) const char *q = end(); const void *(*r)() = &retval; // CHECK: @s // CHECK-SAME: addrspace(1) global ptr null +// WITH-NONZERO-DEFAULT-AS: addrspace(1) global ptr addrspace(4) null const void *s = observable_addr(); // CHECK: define linkonce_odr noundef ptr @_Z6retvalIXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEEEPKvv() +// WITH-NONZERO-DEFAULT-AS: define linkonce_odr {{.*}} noundef ptr addrspace(4) @_Z6retvalIXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEEEPKvv() // CHECK: ret ptr addrspacecast (ptr addrspace(1) [[HELLO]] to ptr) +// WITH-NONZERO-DEFAULT-AS: ret ptr addrspace(4) addrspacecast (ptr addrspace(1) [[HELLO]] to ptr addrspace(4)) // CHECK: define linkonce_odr noundef ptr @_Z15observable_addrIXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEEEPKvv() +// WITH-NONZERO-DEFAULT-AS: define linkonce_odr {{.*}} noundef ptr addrspace(4) @_Z15observable_addrIXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEEEPKvv() // CHECK: %call = call noundef ptr @_Z6calleePK1S(ptr noundef addrspacecast (ptr addrspace(1) [[HELLO]] to ptr)) +// WITH-NONZERO-DEFAULT-AS: %call = call {{.*}} noundef ptr addrspace(4) @_Z6calleePK1S(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) [[HELLO]] to ptr addrspace(4))) // CHECK: declare noundef ptr @_Z6calleePK1S(ptr noundef) +// WITH-NONZERO-DEFAULT-AS: declare {{.*}} noundef ptr addrspace(4) @_Z6calleePK1S(ptr addrspace(4) noundef) diff --git a/clang/test/CodeGenCXX/throw-expression-typeinfo-in-address-space.cpp b/clang/test/CodeGenCXX/throw-expression-typeinfo-in-address-space.cpp index d8c23d427e67a350c6b51f96b2b75bf78b3f6216..3acbdd8fd97ee0f4d0fe4193cd16420dd80324a3 100644 --- a/clang/test/CodeGenCXX/throw-expression-typeinfo-in-address-space.cpp +++ b/clang/test/CodeGenCXX/throw-expression-typeinfo-in-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple amdgcn-amd-amdhsa -emit-llvm -fcxx-exceptions -fexceptions -std=c++11 -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple spirv64-unknown-unknown -fsycl-is-device -emit-llvm -fcxx-exceptions -fexceptions -std=c++11 -o - | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS struct X { ~X(); @@ -15,3 +16,4 @@ void f() { } // CHECK: declare void @__cxa_throw(ptr, ptr addrspace(1), ptr) +// WITH-NONZERO-DEFAULT-AS: declare{{.*}} void @__cxa_throw(ptr addrspace(4), ptr addrspace(1), ptr addrspace(4)) diff --git a/clang/test/CodeGenCXX/try-catch-with-address-space.cpp b/clang/test/CodeGenCXX/try-catch-with-address-space.cpp index 279d29f50fd41010916bfed9d41fe70e1c5cec26..412ac6c2872587ee5403e3f063b81e16462a902d 100644 --- a/clang/test/CodeGenCXX/try-catch-with-address-space.cpp +++ b/clang/test/CodeGenCXX/try-catch-with-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s +// RUN: %clang_cc1 %s -triple=spirv64-unknown-unknown -fsycl-is-device -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS struct X { }; @@ -10,7 +11,8 @@ void f() { // CHECK: ptr addrspace(1) @_ZTI1X } catch (const X x) { // CHECK: catch ptr addrspace(1) @_ZTI1X - // CHECK: call i32 @llvm.eh.typeid.for(ptr addrspacecast (ptr addrspace(1) @_ZTI1X to ptr)) + // CHECK: call i32 @llvm.eh.typeid.for.p0(ptr addrspacecast (ptr addrspace(1) @_ZTI1X to ptr)) + // WITH-NONZERO-DEFAULT-AS: call i32 @llvm.eh.typeid.for.p4(ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTI1X to ptr addrspace(4))) } } @@ -20,6 +22,7 @@ void h() { // CHECK: ptr addrspace(1) @_ZTIPKc } catch (char const(&)[4]) { // CHECK: catch ptr addrspace(1) @_ZTIA4_c - // CHECK: call i32 @llvm.eh.typeid.for(ptr addrspacecast (ptr addrspace(1) @_ZTIA4_c to ptr)) + // CHECK: call i32 @llvm.eh.typeid.for.p0(ptr addrspacecast (ptr addrspace(1) @_ZTIA4_c to ptr)) + // WITH-NONZERO-DEFAULT-AS: call i32 @llvm.eh.typeid.for.p4(ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIA4_c to ptr addrspace(4))) } } diff --git a/clang/test/CodeGenCXX/typeid-cxx11-with-address-space.cpp b/clang/test/CodeGenCXX/typeid-cxx11-with-address-space.cpp index c4e7d36acff130093601d921f1e59a8f4238abc5..f6dc38ec9f2925acc8b6cd3d2d97fb0cd7875653 100644 --- a/clang/test/CodeGenCXX/typeid-cxx11-with-address-space.cpp +++ b/clang/test/CodeGenCXX/typeid-cxx11-with-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -I%S %s -triple amdgcn-amd-amdhsa -emit-llvm -std=c++11 -o - | FileCheck %s +// RUN: %clang_cc1 -I%S %s -triple spirv64-unknown-unknown -fsycl-is-device -emit-llvm -std=c++11 -o - | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS #include namespace Test1 { @@ -19,14 +20,17 @@ struct B : virtual A {}; struct C { int n; }; // CHECK: @_ZN5Test15itemsE ={{.*}} constant [4 x {{.*}}] [{{.*}} ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11AE to ptr), {{.*}} @_ZN5Test19make_implINS_1AEEEPvv {{.*}} ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11BE to ptr), {{.*}} @_ZN5Test19make_implINS_1BEEEPvv {{.*}} ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11CE to ptr), {{.*}} @_ZN5Test19make_implINS_1CEEEPvv {{.*}} ptr addrspacecast (ptr addrspace(1) @_ZTIi to ptr), {{.*}} @_ZN5Test19make_implIiEEPvv }] +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test15itemsE ={{.*}} addrspace(1) constant [4 x {{.*}}] [{{.*}} ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIN5Test11AE to ptr addrspace(4)), {{.*}} @_ZN5Test19make_implINS_1AEEEPvv {{.*}} ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIN5Test11BE to ptr addrspace(4)), {{.*}} @_ZN5Test19make_implINS_1BEEEPvv {{.*}} ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIN5Test11CE to ptr addrspace(4)), {{.*}} @_ZN5Test19make_implINS_1CEEEPvv {{.*}} ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIi to ptr addrspace(4)), {{.*}} @_ZN5Test19make_implIiEEPvv }] extern constexpr Item items[] = { item("A"), item("B"), item("C"), item("int") }; // CHECK: @_ZN5Test11xE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11AE to ptr), align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test11xE ={{.*}} addrspace(1) constant ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIN5Test11AE to ptr addrspace(4)), align 8 constexpr auto &x = items[0].ti; // CHECK: @_ZN5Test11yE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11BE to ptr), align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test11yE ={{.*}} addrspace(1) constant ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIN5Test11BE to ptr addrspace(4)), align 8 constexpr auto &y = typeid(B{}); } diff --git a/clang/test/CodeGenCXX/typeid-with-address-space.cpp b/clang/test/CodeGenCXX/typeid-with-address-space.cpp index b439770a8b631e8081182b9ce2c49feb28685a05..98af17f4fc88881ce64bab0cf231f1b5b906c46f 100644 --- a/clang/test/CodeGenCXX/typeid-with-address-space.cpp +++ b/clang/test/CodeGenCXX/typeid-with-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -I%S %s -triple amdgcn-amd-amdhsa -emit-llvm -fcxx-exceptions -fexceptions -o - | FileCheck %s +// RUN: %clang_cc1 -I%S %s -triple spirv64-unknown-unknown -fsycl-is-device -emit-llvm -fcxx-exceptions -fexceptions -o - | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS #include namespace Test1 { @@ -7,19 +8,23 @@ namespace Test1 { struct A { virtual void f(); }; // CHECK: @_ZN5Test16int_tiE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIi to ptr), align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test16int_tiE ={{.*}} constant ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIi to ptr addrspace(4)), align 8 const std::type_info &int_ti = typeid(int); // CHECK: @_ZN5Test14A_tiE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11AE to ptr), align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test14A_tiE ={{.*}} constant ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIN5Test11AE to ptr addrspace(4)), align 8 const std::type_info &A_ti = typeid(const volatile A &); volatile char c; // CHECK: @_ZN5Test14c_tiE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIc to ptr), align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test14c_tiE ={{.*}} constant ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIc to ptr addrspace(4)), align 8 const std::type_info &c_ti = typeid(c); extern const double &d; // CHECK: @_ZN5Test14d_tiE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTId to ptr), align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test14d_tiE ={{.*}} constant ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTId to ptr addrspace(4)), align 8 const std::type_info &d_ti = typeid(d); extern A &a; @@ -28,18 +33,24 @@ extern A &a; const std::type_info &a_ti = typeid(a); // CHECK: @_ZN5Test18A10_c_tiE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIA10_c to ptr), align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test18A10_c_tiE ={{.*}} constant ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIA10_c to ptr addrspace(4)), align 8 const std::type_info &A10_c_ti = typeid(char const[10]); // CHECK-LABEL: define{{.*}} ptr @_ZN5Test11fEv // CHECK-SAME: personality ptr @__gxx_personality_v0 +// WITH-NONZERO-DEFAULT-AS-LABEL: define{{.*}} ptr addrspace(4) @_ZN5Test11fEv +// WITH-NONZERO-DEFAULT-AS-SAME: personality ptr @__gxx_personality_v0 const char *f() { try { // CHECK: br i1 // CHECK: invoke void @__cxa_bad_typeid() [[NR:#[0-9]+]] + // WITH-NONZERO-DEFAULT-AS: invoke{{.*}} void @__cxa_bad_typeid() [[NR:#[0-9]+]] return typeid(*static_cast(0)).name(); } catch (...) { // CHECK: landingpad { ptr, i32 } // CHECK-NEXT: catch ptr null + // WITH-NONZERO-DEFAULT-AS: landingpad { ptr addrspace(4), i32 } + // WITH-NONZERO-DEFAULT-AS-NEXT: catch ptr addrspace(4) null } return 0; diff --git a/clang/test/CodeGenCXX/typeinfo-with-address-space.cpp b/clang/test/CodeGenCXX/typeinfo-with-address-space.cpp index 80f6ab0903e51bc1aff67f88308c68561567615a..350303cc6e9b34b7f5a5caaf3775e9cb8bdf0330 100644 --- a/clang/test/CodeGenCXX/typeinfo-with-address-space.cpp +++ b/clang/test/CodeGenCXX/typeinfo-with-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -I%S %s -triple amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck %s -check-prefix=AS +// RUN: %clang_cc1 -I%S %s -triple spirv64-unknown-unknown -fsycl-is-device -emit-llvm -o - | FileCheck %s -check-prefix=NONZERO-DEFAULT-AS // RUN: %clang_cc1 -I%S %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s -check-prefix=NO-AS #include @@ -25,24 +26,30 @@ class B : A { unsigned long Fn(B& b) { // AS: %call = call noundef zeroext i1 @_ZNKSt9type_infoeqERKS_(ptr {{.*}} addrspacecast (ptr addrspace(1) @_ZTISt9type_info to ptr), ptr {{.*}} %2) +// NONZERO-DEFAULT-AS: %call = call{{.*}} noundef zeroext i1 @_ZNKSt9type_infoeqERKS_(ptr addrspace(4) {{.*}} addrspacecast (ptr addrspace(1) @_ZTISt9type_info to ptr addrspace(4)), ptr addrspace(4) {{.*}} %2) // NO-AS: %call = call noundef zeroext i1 @_ZNKSt9type_infoeqERKS_(ptr {{.*}} @_ZTISt9type_info, ptr {{.*}} %2) if (typeid(std::type_info) == typeid(b)) return 42; // AS: %call2 = call noundef zeroext i1 @_ZNKSt9type_infoneERKS_(ptr {{.*}} addrspacecast (ptr addrspace(1) @_ZTIi to ptr), ptr {{.*}} %5) +// NONZERO-DEFAULT-AS: %call2 = call{{.*}} noundef zeroext i1 @_ZNKSt9type_infoneERKS_(ptr addrspace(4) {{.*}} addrspacecast (ptr addrspace(1) @_ZTIi to ptr addrspace(4)), ptr addrspace(4) {{.*}} %5) // NO-AS: %call2 = call noundef zeroext i1 @_ZNKSt9type_infoneERKS_(ptr {{.*}} @_ZTIi, ptr {{.*}} %5) if (typeid(int) != typeid(b)) return 1712; // AS: %call5 = call noundef ptr @_ZNKSt9type_info4nameEv(ptr {{.*}} addrspacecast (ptr addrspace(1) @_ZTI1A to ptr)) +// NONZERO-DEFAULT-AS: %call5 = call{{.*}} noundef ptr addrspace(4) @_ZNKSt9type_info4nameEv(ptr addrspace(4) {{.*}} addrspacecast (ptr addrspace(1) @_ZTI1A to ptr addrspace(4))) // NO-AS: %call5 = call noundef ptr @_ZNKSt9type_info4nameEv(ptr {{.*}} @_ZTI1A) // AS: %call7 = call noundef ptr @_ZNKSt9type_info4nameEv(ptr {{.*}} %8) +// NONZERO-DEFAULT-AS: %call7 = call{{.*}} noundef ptr addrspace(4) @_ZNKSt9type_info4nameEv(ptr addrspace(4) {{.*}} %8) // NO-AS: %call7 = call noundef ptr @_ZNKSt9type_info4nameEv(ptr {{.*}} %8) if (typeid(A).name() == typeid(b).name()) return 0; // AS: %call11 = call noundef zeroext i1 @_ZNKSt9type_info6beforeERKS_(ptr {{.*}} %11, ptr {{.*}} addrspacecast (ptr addrspace(1) @_ZTIf to ptr)) +// NONZERO-DEFAULT-AS: %call11 = call{{.*}} noundef zeroext i1 @_ZNKSt9type_info6beforeERKS_(ptr addrspace(4) {{.*}} %11, ptr addrspace(4) {{.*}} addrspacecast (ptr addrspace(1) @_ZTIf to ptr addrspace(4))) // NO-AS: %call11 = call noundef zeroext i1 @_ZNKSt9type_info6beforeERKS_(ptr {{.*}} %11, ptr {{.*}} @_ZTIf) if (typeid(b).before(typeid(float))) return 1; // AS: %call15 = call noundef i64 @_ZNKSt9type_info9hash_codeEv(ptr {{.*}} %14) +// NONZERO-DEFAULT-AS: %call15 = call{{.*}} noundef i64 @_ZNKSt9type_info9hash_codeEv(ptr addrspace(4) {{.*}} %14) // NO-AS: %call15 = call noundef i64 @_ZNKSt9type_info9hash_codeEv(ptr {{.*}} %14) return typeid(b).hash_code(); } diff --git a/clang/test/CodeGenCXX/vtable-assume-load-address-space.cpp b/clang/test/CodeGenCXX/vtable-assume-load-address-space.cpp index d765fe94d9b084ed9e25767527492d4a7ecd179f..ecafa99d8be00f7582170f18982be521d5d5a663 100644 --- a/clang/test/CodeGenCXX/vtable-assume-load-address-space.cpp +++ b/clang/test/CodeGenCXX/vtable-assume-load-address-space.cpp @@ -1,14 +1,17 @@ // RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -std=c++11 -emit-llvm -o %t.ll -O1 -disable-llvm-passes -fms-extensions -fstrict-vtable-pointers +// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-passes -fms-extensions -fstrict-vtable-pointers +// RUN: %clang_cc1 %s -triple=spirv64-unknown-unknown -fsycl-is-device -std=c++11 -emit-llvm -o %t.ll -O1 -disable-llvm-passes -fms-extensions -fstrict-vtable-pointers // FIXME: Assume load should not require -fstrict-vtable-pointers // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s // RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s // RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s // RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s -// RUN: FileCheck --check-prefix=CHECK5 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s // RUN: FileCheck --check-prefix=CHECK6 --input-file=%t.ll %s // RUN: FileCheck --check-prefix=CHECK7 --input-file=%t.ll %s // RUN: FileCheck --check-prefix=CHECK8 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK9 --input-file=%t.ll %s namespace test1 { struct A { @@ -23,8 +26,8 @@ struct B : A { void g(A *a) { a->foo(); } // CHECK1-LABEL: define{{.*}} void @_ZN5test14fooAEv() -// CHECK1: call void @_ZN5test11AC1Ev(ptr -// CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr %{{.*}} +// CHECK1: call{{.*}} void @_ZN5test11AC1Ev(ptr {{((addrspace(4)){0,1})}} +// CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr {{((addrspace(4)){0,1})}}{{.*}}%{{.*}} // CHECK1: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test11AE, i32 0, i32 0, i32 2) // CHECK1: call void @llvm.assume(i1 %[[CMP]]) // CHECK1-LABEL: {{^}}} @@ -35,8 +38,8 @@ void fooA() { } // CHECK1-LABEL: define{{.*}} void @_ZN5test14fooBEv() -// CHECK1: call void @_ZN5test11BC1Ev(ptr {{[^,]*}} %{{.*}}) -// CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr %{{.*}} +// CHECK1: call{{.*}} void @_ZN5test11BC1Ev(ptr {{[^,]*}} %{{.*}}) +// CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr {{((addrspace(4)){0,1})}}{{.*}}%{{.*}} // CHECK1: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test11BE, i32 0, i32 0, i32 2) // CHECK1: call void @llvm.assume(i1 %[[CMP]]) // CHECK1-LABEL: {{^}}} @@ -46,7 +49,7 @@ void fooB() { g(&b); } // there should not be any assumes in the ctor that calls base ctor -// CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(ptr +// CHECK1-LABEL: define linkonce_odr{{.*}} void @_ZN5test11BC2Ev(ptr // CHECK1-NOT: @llvm.assume( // CHECK1-LABEL: {{^}}} } @@ -69,17 +72,17 @@ void g(A *a) { a->foo(); } void h(B *b) { b->bar(); } // CHECK2-LABEL: define{{.*}} void @_ZN5test24testEv() -// CHECK2: call void @_ZN5test21CC1Ev(ptr +// CHECK2: call{{.*}} void @_ZN5test21CC1Ev(ptr // CHECK2: %[[VTABLE:.*]] = load ptr addrspace(1), ptr {{.*}} // CHECK2: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test21CE, i32 0, i32 0, i32 2) // CHECK2: call void @llvm.assume(i1 %[[CMP]]) -// CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i64 8 -// CHECK2: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr %[[ADD_PTR]] +// CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr {{((addrspace(4)){0,1})}}{{.*}}%{{.*}}, i64 8 +// CHECK2: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr {{((addrspace(4)){0,1})}}{{.*}}%[[ADD_PTR]] // CHECK2: %[[CMP2:.*]] = icmp eq ptr addrspace(1) %[[VTABLE2]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test21CE, i32 0, i32 1, i32 2) // CHECK2: call void @llvm.assume(i1 %[[CMP2]]) -// CHECK2: call void @_ZN5test21gEPNS_1AE( +// CHECK2: call{{.*}} void @_ZN5test21gEPNS_1AE( // CHECK2-LABEL: {{^}}} void test() { @@ -106,7 +109,7 @@ struct C : virtual A, B { void g(B *a) { a->foo(); } // CHECK3-LABEL: define{{.*}} void @_ZN5test34testEv() -// CHECK3: call void @_ZN5test31CC1Ev(ptr +// CHECK3: call{{.*}} void @_ZN5test31CC1Ev(ptr // CHECK3: %[[CMP:.*]] = icmp eq ptr addrspace(1) %{{.*}}, getelementptr inbounds inrange(-24, 8) ({ [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test31CE, i32 0, i32 0, i32 3) // CHECK3: call void @llvm.assume(i1 %[[CMP]]) // CHECK3-LABLEL: } @@ -134,12 +137,12 @@ struct C : B { void g(C *c) { c->foo(); } // CHECK4-LABEL: define{{.*}} void @_ZN5test44testEv() -// CHECK4: call void @_ZN5test41CC1Ev(ptr -// CHECK4: %[[VTABLE:.*]] = load ptr addrspace(1), ptr %{{.*}} +// CHECK4: call{{.*}} void @_ZN5test41CC1Ev(ptr +// CHECK4: %[[VTABLE:.*]] = load ptr addrspace(1), ptr {{((addrspace(4)){0,1})}}{{.*}}%{{.*}} // CHECK4: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-32, 8) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test41CE, i32 0, i32 0, i32 4) // CHECK4: call void @llvm.assume(i1 %[[CMP]] -// CHECK4: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr %{{.*}} +// CHECK4: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr {{((addrspace(4)){0,1})}}{{.*}}%{{.*}} // CHECK4: %[[CMP2:.*]] = icmp eq ptr addrspace(1) %[[VTABLE2]], getelementptr inbounds inrange(-32, 8) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test41CE, i32 0, i32 0, i32 4) // CHECK4: call void @llvm.assume(i1 %[[CMP2]]) // CHECK4-LABEL: {{^}}} @@ -150,6 +153,27 @@ void test() { } } // test4 +namespace testMS { + +struct __declspec(novtable) S { + virtual void foo(); +}; + +void g(S &s) { s.foo(); } + +// if struct has novtable specifier, then we can't generate assumes +// CHECK-MS-LABEL: define dso_local void @"?test@testMS@@YAXXZ"() +// CHECK-MS: call x86_thiscallcc noundef ptr @"??0S@testMS@@QAE@XZ"( +// CHECK-MS-NOT: @llvm.assume +// CHECK-MS-LABEL: {{^}}} + +void test() { + S s; + g(s); +} + +} // testMS + namespace test6 { struct A { A(); @@ -161,17 +185,17 @@ struct B : A { }; // FIXME: Because A's vtable is external, and no virtual functions are hidden, // it's safe to generate assumption loads. -// CHECK5-LABEL: define{{.*}} void @_ZN5test61gEv() -// CHECK5: call void @_ZN5test61AC1Ev( -// CHECK5-NOT: call void @llvm.assume( +// CHECK6-LABEL: define{{.*}} void @_ZN5test61gEv() +// CHECK6: call{{.*}} void @_ZN5test61AC1Ev( +// CHECK6-NOT: call void @llvm.assume( // We can't emit assumption loads for B, because if we would refer to vtable // it would refer to functions that will not be able to find (like implicit // inline destructor). -// CHECK5-LABEL: call void @_ZN5test61BC1Ev( -// CHECK5-NOT: call void @llvm.assume( -// CHECK5-LABEL: {{^}}} +// CHECK6-LABEL: call{{.*}} void @_ZN5test61BC1Ev( +// CHECK6-NOT: call void @llvm.assume( +// CHECK6-LABEL: {{^}}} void g() { A *a = new A; B *b = new B; @@ -180,7 +204,7 @@ void g() { namespace test7 { // Because A's key function is defined here, vtable is generated in this TU -// CHECK6: @_ZTVN5test71AE ={{.*}} unnamed_addr addrspace(1) constant +// CHECK7: @_ZTVN5test71AE ={{.*}} unnamed_addr addrspace(1) constant struct A { A(); virtual void foo(); @@ -188,10 +212,10 @@ struct A { }; void A::foo() {} -// CHECK6-LABEL: define{{.*}} void @_ZN5test71gEv() -// CHECK6: call void @_ZN5test71AC1Ev( -// CHECK6: call void @llvm.assume( -// CHECK6-LABEL: {{^}}} +// CHECK7-LABEL: define{{.*}} void @_ZN5test71gEv() +// CHECK7: call{{.*}} void @_ZN5test71AC1Ev( +// CHECK7: call void @llvm.assume( +// CHECK7-LABEL: {{^}}} void g() { A *a = new A(); a->bar(); @@ -205,14 +229,14 @@ struct A { virtual void bar(); }; -// CHECK7-DAG: @_ZTVN5test81BE = available_externally unnamed_addr addrspace(1) constant +// CHECK8-DAG: @_ZTVN5test81BE = available_externally unnamed_addr addrspace(1) constant struct B : A { B(); void foo(); void bar(); }; -// CHECK7-DAG: @_ZTVN5test81CE = linkonce_odr unnamed_addr addrspace(1) constant +// CHECK8-DAG: @_ZTVN5test81CE = linkonce_odr unnamed_addr addrspace(1) constant struct C : A { C(); void bar(); @@ -227,14 +251,14 @@ struct D : A { }; void D::bar() {} -// CHECK7-DAG: @_ZTVN5test81EE = linkonce_odr unnamed_addr addrspace(1) constant +// CHECK8-DAG: @_ZTVN5test81EE = linkonce_odr unnamed_addr addrspace(1) constant struct E : A { E(); }; -// CHECK7-LABEL: define{{.*}} void @_ZN5test81bEv() -// CHECK7: call void @llvm.assume( -// CHECK7-LABEL: {{^}}} +// CHECK8-LABEL: define{{.*}} void @_ZN5test81bEv() +// CHECK8: call void @llvm.assume( +// CHECK8-LABEL: {{^}}} void b() { B b; b.bar(); @@ -243,26 +267,26 @@ void b() { // FIXME: C has inline virtual functions which prohibits as from generating // assumption loads, but because vtable is generated in this TU (key function // defined here) it would be correct to refer to it. -// CHECK7-LABEL: define{{.*}} void @_ZN5test81cEv() -// CHECK7-NOT: call void @llvm.assume( -// CHECK7-LABEL: {{^}}} +// CHECK8-LABEL: define{{.*}} void @_ZN5test81cEv() +// CHECK8-NOT: call void @llvm.assume( +// CHECK8-LABEL: {{^}}} void c() { C c; c.bar(); } // FIXME: We could generate assumption loads here. -// CHECK7-LABEL: define{{.*}} void @_ZN5test81dEv() -// CHECK7-NOT: call void @llvm.assume( -// CHECK7-LABEL: {{^}}} +// CHECK8-LABEL: define{{.*}} void @_ZN5test81dEv() +// CHECK8-NOT: call void @llvm.assume( +// CHECK8-LABEL: {{^}}} void d() { D d; d.bar(); } -// CHECK7-LABEL: define{{.*}} void @_ZN5test81eEv() -// CHECK7: call void @llvm.assume( -// CHECK7-LABEL: {{^}}} +// CHECK8-LABEL: define{{.*}} void @_ZN5test81eEv() +// CHECK8: call void @llvm.assume( +// CHECK8-LABEL: {{^}}} void e() { E e; e.bar(); @@ -276,9 +300,9 @@ struct S { __attribute__((visibility("hidden"))) virtual void doStuff(); }; -// CHECK8-LABEL: define{{.*}} void @_ZN5test94testEv() -// CHECK8-NOT: @llvm.assume( -// CHECK8: } +// CHECK9-LABEL: define{{.*}} void @_ZN5test94testEv() +// CHECK9-NOT: @llvm.assume( +// CHECK9: } void test() { S *s = new S(); s->doStuff(); diff --git a/clang/test/CodeGenCXX/vtable-pointer-initialization-address-space.cpp b/clang/test/CodeGenCXX/vtable-pointer-initialization-address-space.cpp index a3f12f0ebfc87bd237d3f85d007e2e9e31f0168e..876d0845cc515765b0becc04042ab18b7fafc6a2 100644 --- a/clang/test/CodeGenCXX/vtable-pointer-initialization-address-space.cpp +++ b/clang/test/CodeGenCXX/vtable-pointer-initialization-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -std=c++11 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=spirv64-unknown-unknown -fsycl-is-device -std=c++11 -emit-llvm -o - | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS struct Field { Field(); @@ -24,6 +25,7 @@ struct A : Base { // CHECK: store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1A, i32 0, i32 0, i32 2) // CHECK: call void @_ZN5FieldC1Ev( // CHECK: ret void +// WITH-NONZERO-DEFAULT-AS-LABEL: define{{.*}} void @_ZN1AC2Ev(ptr addrspace(4) {{[^,]*}} %this) unnamed_addr A::A() { } // CHECK-LABEL: define{{.*}} void @_ZN1AD2Ev(ptr {{[^,]*}} %this) unnamed_addr @@ -31,6 +33,7 @@ A::A() { } // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void +// WITH-NONZERO-DEFAULT-AS-LABEL: define{{.*}} void @_ZN1AD2Ev(ptr addrspace(4) {{[^,]*}} %this) unnamed_addr A::~A() { } struct B : Base { @@ -43,18 +46,22 @@ void f() { B b; } // CHECK-LABEL: define linkonce_odr void @_ZN1BC1Ev(ptr {{[^,]*}} %this) unnamed_addr // CHECK: call void @_ZN1BC2Ev( +// WITH-NONZERO-DEFAULT-AS-LABEL: define linkonce_odr{{.*}} void @_ZN1BC1Ev(ptr addrspace(4) {{[^,]*}} %this) unnamed_addr // CHECK-LABEL: define linkonce_odr void @_ZN1BD1Ev(ptr {{[^,]*}} %this) unnamed_addr // CHECK: call void @_ZN1BD2Ev( +// WITH-NONZERO-DEFAULT-AS-LABEL: define linkonce_odr{{.*}} void @_ZN1BD1Ev(ptr addrspace(4) {{[^,]*}} %this) unnamed_addr // CHECK-LABEL: define linkonce_odr void @_ZN1BC2Ev(ptr {{[^,]*}} %this) unnamed_addr // CHECK: call void @_ZN4BaseC2Ev( // CHECK: store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2) // CHECK: call void @_ZN5FieldC1Ev // CHECK: ret void +// WITH-NONZERO-DEFAULT-AS-LABEL: define linkonce_odr{{.*}} void @_ZN1BC2Ev(ptr addrspace(4) {{[^,]*}} %this) unnamed_addr // CHECK-LABEL: define linkonce_odr void @_ZN1BD2Ev(ptr {{[^,]*}} %this) unnamed_addr // CHECK: store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void +// WITH-NONZERO-DEFAULT-AS-LABEL: define linkonce_odr{{.*}} void @_ZN1BD2Ev(ptr addrspace(4) {{[^,]*}} %this) unnamed_addr diff --git a/clang/test/CodeGenCXX/vtt-address-space.cpp b/clang/test/CodeGenCXX/vtt-address-space.cpp index 24f4e2a755da0489ecb010890af9967d1a39197c..4c3d0a534611c733cea0826358e3762e8e93bfaa 100644 --- a/clang/test/CodeGenCXX/vtt-address-space.cpp +++ b/clang/test/CodeGenCXX/vtt-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -std=c++11 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=spirv64-unknown-unknown -fsycl-is-device -std=c++11 -emit-llvm -o - | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS // This is the sample from the C++ Itanium ABI, p2.6.2. namespace Test { @@ -25,3 +26,9 @@ namespace Test { // CHECK: define linkonce_odr void @_ZN4Test2V2C2Ev(ptr noundef nonnull align 8 dereferenceable(20) %this, ptr addrspace(1) noundef %vtt) // CHECK: define linkonce_odr void @_ZN4Test2C1C2Ev(ptr noundef nonnull align 8 dereferenceable(12) %this, ptr addrspace(1) noundef %vtt) // CHECK: define linkonce_odr void @_ZN4Test2C2C2Ev(ptr noundef nonnull align 8 dereferenceable(12) %this, ptr addrspace(1) noundef %vtt) +// WITH-NONZERO-DEFAULT-AS: call {{.*}} void @_ZN4Test2V2C2Ev(ptr addrspace(4) noundef align 8 dereferenceable_or_null(20) %2, ptr addrspace(1) noundef getelementptr inbounds ([13 x ptr addrspace(1)], ptr addrspace(1) @_ZTTN4Test1DE, i64 0, i64 11)) +// WITH-NONZERO-DEFAULT-AS: call {{.*}} void @_ZN4Test2C1C2Ev(ptr addrspace(4) noundef align 8 dereferenceable_or_null(12) %this1, ptr addrspace(1) noundef getelementptr inbounds ([13 x ptr addrspace(1)], ptr addrspace(1) @_ZTTN4Test1DE, i64 0, i64 1)) +// WITH-NONZERO-DEFAULT-AS: call {{.*}} void @_ZN4Test2C2C2Ev(ptr addrspace(4) noundef align 8 dereferenceable_or_null(12) %3, ptr addrspace(1) noundef getelementptr inbounds ([13 x ptr addrspace(1)], ptr addrspace(1) @_ZTTN4Test1DE, i64 0, i64 3)) +// WITH-NONZERO-DEFAULT-AS: define linkonce_odr {{.*}} void @_ZN4Test2V2C2Ev(ptr addrspace(4) noundef align 8 dereferenceable_or_null(20) %this, ptr addrspace(1) noundef %vtt) +// WITH-NONZERO-DEFAULT-AS: define linkonce_odr {{.*}} void @_ZN4Test2C1C2Ev(ptr addrspace(4) noundef align 8 dereferenceable_or_null(12) %this, ptr addrspace(1) noundef %vtt) +// WITH-NONZERO-DEFAULT-AS: define linkonce_odr {{.*}} void @_ZN4Test2C2C2Ev(ptr addrspace(4) noundef align 8 dereferenceable_or_null(12) %this, ptr addrspace(1) noundef %vtt) diff --git a/clang/test/CodeGenCXX/wasm-eh.cpp b/clang/test/CodeGenCXX/wasm-eh.cpp index af023f52191b979c9e5bf8535e5c7f992e1853df..1b17498ba9ce9f02a55564d826997840d9984aab 100644 --- a/clang/test/CodeGenCXX/wasm-eh.cpp +++ b/clang/test/CodeGenCXX/wasm-eh.cpp @@ -34,7 +34,7 @@ void test0() { // CHECK-NEXT: %[[EXN:.*]] = call ptr @llvm.wasm.get.exception(token %[[CATCHPAD]]) // CHECK-NEXT: store ptr %[[EXN]], ptr %exn.slot // CHECK-NEXT: %[[SELECTOR:.*]] = call i32 @llvm.wasm.get.ehselector(token %[[CATCHPAD]]) -// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(ptr @_ZTIi) #7 +// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) #7 // CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]] // CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_INT_BB:.*]], label %[[CATCH_FALLTHROUGH_BB:.*]] @@ -51,7 +51,7 @@ void test0() { // CHECK-NEXT: br label %[[TRY_CONT_BB:.*]] // CHECK: [[CATCH_FALLTHROUGH_BB]] -// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(ptr @_ZTId) #7 +// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTId) #7 // CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]] // CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_FLOAT_BB:.*]], label %[[RETHROW_BB:.*]] diff --git a/clang/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp b/clang/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp index 3a5693275824fd31427c40de07dfe702b7bc167a..d281826ee70fe6ff524d1235fd95b6d0e35f4d73 100644 --- a/clang/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp +++ b/clang/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -std=c++11 -triple i686-windows -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MS -// RUN: %clang_cc1 -std=c++11 -triple i686-windows-itanium -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-IA -// RUN: %clang_cc1 -std=c++11 -triple x86_64-scei-ps4 -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-PS4 -// RUN: %clang_cc1 -std=c++11 -triple x86_64-sie-ps5 -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-PS4 +// RUN: %clang_cc1 -std=c++11 -triple i686-windows-itanium -fdeclspec -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple x86_64-scei-ps4 -fdeclspec -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple x86_64-sie-ps5 -fdeclspec -emit-llvm %s -o - | FileCheck %s template struct s {}; @@ -15,8 +15,5 @@ template class __declspec(dllexport) t; // CHECK-MS: dllexport {{.*}} @"??4?$t@D@@QAEAAV0@ABV0@@Z" // CHECK-MS: dllexport {{.*}} @"??4?$s@D@@QAEAAU0@ABU0@@Z" -// CHECK-IA: dllexport {{.*}} @_ZN1tIcEaSERKS0_ -// CHECK-IA: dllexport {{.*}} @_ZN1sIcEaSERKS0_ - -// CHECK-PS4-NOT: @_ZN1tIcEaSERKS0_ -// CHECK-PS4-NOT: @_ZN1sIcEaSERKS0_ +// CHECK: dllexport {{.*}} @_ZN1tIcEaSERKS0_ +// CHECK: dllexport {{.*}} @_ZN1sIcEaSERKS0_ diff --git a/clang/test/CodeGenCXX/windows-itanium-dllexport.cpp b/clang/test/CodeGenCXX/windows-itanium-dllexport.cpp index c09fa30d761af43896cde2de0a0e19c71f78ea27..334cebff99da7cd274b44cc319facf30efcb2010 100644 --- a/clang/test/CodeGenCXX/windows-itanium-dllexport.cpp +++ b/clang/test/CodeGenCXX/windows-itanium-dllexport.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -emit-llvm -triple i686-windows-itanium -fdeclspec %s -o - | FileCheck %s --check-prefixes=CHECK,WI -// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps4 -fdeclspec %s -o - | FileCheck %s --check-prefixes=CHECK,PS4 -// RUN: %clang_cc1 -emit-llvm -triple x86_64-sie-ps5 -fdeclspec %s -o - | FileCheck %s --check-prefixes=CHECK,PS4 +// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps4 -fdeclspec %s -o - | FileCheck %s --check-prefixes=CHECK,PS +// RUN: %clang_cc1 -emit-llvm -triple x86_64-sie-ps5 -fdeclspec %s -o - | FileCheck %s --check-prefixes=CHECK,PS #define JOIN2(x, y) x##y #define JOIN(x, y) JOIN2(x, y) @@ -27,18 +27,14 @@ template class __declspec(dllexport) c; extern template class c; template class __declspec(dllexport) c; -// WI: define {{.*}} dllexport {{.*}} @_ZN1cIcEaSERKS0_ -// WI: define {{.*}} dllexport {{.*}} @_ZN1cIcE1fEv -// PS4-NOT: @_ZN1cIcEaSERKS0_ -// PS4: define weak_odr void @_ZN1cIcE1fEv +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcEaSERKS0_ +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcE1fEv c g; template class __declspec(dllexport) c; -// WI: define {{.*}} dllexport {{.*}} @_ZN1cIdEaSERKS0_ -// WI: define {{.*}} dllexport {{.*}} @_ZN1cIdE1fEv -// PS4-NOT: @_ZN1cIdEaSERKS0_ -// PS4: define weak_odr void @_ZN1cIdE1fEv +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdEaSERKS0_ +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdE1fEv template struct outer { @@ -59,4 +55,4 @@ USEMEMFUNC(outer::inner, f) // CHECK-DAG: declare dllimport {{.*}} @_ZN5outerIcE1fEv // WI-DAG: define {{.*}} @_ZN5outerIcE5inner1fEv -// PS4-DAG: declare {{.*}} @_ZN5outerIcE5inner1fEv +// PS-DAG: declare {{.*}} @_ZN5outerIcE5inner1fEv diff --git a/clang/test/CoverageMapping/coroutine.cpp b/clang/test/CoverageMapping/coroutine.cpp index 0105005d198a1ccc4025425bce71308a6220d822..d322bc351a7276ea8d30350ba0e5fee743ff2532 100644 --- a/clang/test/CoverageMapping/coroutine.cpp +++ b/clang/test/CoverageMapping/coroutine.cpp @@ -32,6 +32,7 @@ struct std::coroutine_traits { suspend_always final_suspend() noexcept; void unhandled_exception() noexcept; void return_value(int); + suspend_always yield_value(int); }; }; @@ -45,3 +46,21 @@ int f1(int x) { // CHECK-NEXT: File 0, [[@LINE]]:15 -> [[@LINE+8]]:2 = #0 } // CHECK-NEXT: File 0, [[@LINE-2]]:10 -> [[@LINE]]:4 = (#0 - #1) co_return x; // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE]]:3 = #1 } // CHECK-NEXT: File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:14 = #1 + +// CHECK-LABEL: _Z2f2i: +// CHECK-NEXT: File 0, [[@LINE+1]]:15 -> [[@LINE+15]]:2 = #0 +int f2(int x) { +// CHECK-NEXT: File 0, [[@LINE+5]]:13 -> [[@LINE+5]]:18 = #0 +// CHECK-NEXT: Branch,File 0, [[@LINE+4]]:13 -> [[@LINE+4]]:18 = #1, (#0 - #1) +// CHECK-NEXT: Gap,File 0, [[@LINE+3]]:20 -> [[@LINE+3]]:21 = #1 +// CHECK-NEXT: File 0, [[@LINE+2]]:21 -> [[@LINE+2]]:37 = #1 +// CHECK-NEXT: File 0, [[@LINE+1]]:40 -> [[@LINE+1]]:56 = (#0 - #1) + co_await (x > 0 ? suspend_always{} : suspend_always{}); +// CHECK-NEXT: File 0, [[@LINE+5]]:12 -> [[@LINE+5]]:17 = #0 +// CHECK-NEXT: Branch,File 0, [[@LINE+4]]:12 -> [[@LINE+4]]:17 = #2, (#0 - #2) +// CHECK-NEXT: Gap,File 0, [[@LINE+3]]:19 -> [[@LINE+3]]:20 = #2 +// CHECK-NEXT: File 0, [[@LINE+2]]:20 -> [[@LINE+2]]:21 = #2 +// CHECK-NEXT: File 0, [[@LINE+1]]:24 -> [[@LINE+1]]:25 = (#0 - #2) + co_yield x > 0 ? 1 : 2; + co_return 0; +} diff --git a/clang/test/CoverageMapping/decomposition.cpp b/clang/test/CoverageMapping/decomposition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..601ea630faeec94e3a7d6719cafacb140276a367 --- /dev/null +++ b/clang/test/CoverageMapping/decomposition.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -triple %itanium_abi_triple -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s | FileCheck %s + +// CHECK-LABEL: _Z19array_decompositioni: +// CHECK-NEXT: File 0, [[@LINE+6]]:32 -> {{[0-9]+}}:2 = #0 +// CHECK-NEXT: File 0, [[@LINE+8]]:20 -> [[@LINE+8]]:25 = #0 +// CHECK-NEXT: Branch,File 0, [[@LINE+7]]:20 -> [[@LINE+7]]:25 = #1, (#0 - #1) +// CHECK-NEXT: Gap,File 0, [[@LINE+6]]:27 -> [[@LINE+6]]:28 = #1 +// CHECK-NEXT: File 0, [[@LINE+5]]:28 -> [[@LINE+5]]:29 = #1 +// CHECK-NEXT: File 0, [[@LINE+4]]:32 -> [[@LINE+4]]:33 = (#0 - #1) +int array_decomposition(int i) { + int a[] = {1, 2, 3}; + int b[] = {4, 5, 6}; + auto [x, y, z] = i > 0 ? a : b; + return x + y + z; +} diff --git a/clang/test/CoverageMapping/mcdc-system-headers.cpp b/clang/test/CoverageMapping/mcdc-system-headers.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a8a3ddbb506fb4c496a6d4a06e922154c297798a --- /dev/null +++ b/clang/test/CoverageMapping/mcdc-system-headers.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -std=c++11 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -fcoverage-mcdc -mllvm -system-headers-coverage -emit-llvm-only -o - %s | FileCheck %s --check-prefixes=CHECK,W_SYS +// RUN: %clang_cc1 -std=c++11 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -fcoverage-mcdc -emit-llvm-only -o - %s | FileCheck %s --check-prefixes=CHECK,X_SYS + +#ifdef IS_SYSHEADER + +#pragma clang system_header +#define CONST 42 +#define EXPR1(x) (x) +#define EXPR2(x) ((x) && (x)) + +#else + +#define IS_SYSHEADER +#include __FILE__ + +// CHECK: _Z5func0i: +int func0(int a) { + // CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:21 = M:0, C:2 + // W_SYS: Expansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:16 = #0 (Expanded file = 1) + // X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = 0, 0 [1,2,0] + return (CONST && a); + // CHECK: Branch,File 0, [[@LINE-1]]:20 -> [[@LINE-1]]:21 = #2, (#1 - #2) [2,0,0] + // W_SYS: Branch,File 1, [[@LINE-16]]:15 -> [[@LINE-16]]:17 = 0, 0 [1,2,0] +} + +// CHECK: _Z5func1ii: +int func1(int a, int b) { + // CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:21 = M:0, C:2 + // CHECK: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:12 = (#0 - #1), #1 [1,0,2] + return (a || EXPR1(b)); + // W_SYS: Expansion,File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:21 = #1 (Expanded file = 1) + // W_SYS: Branch,File 1, [[@LINE-24]]:18 -> [[@LINE-24]]:21 = (#1 - #2), #2 [2,0,0] + // X_SYS: Branch,File 0, [[@LINE-3]]:16 -> [[@LINE-3]]:16 = (#1 - #2), #2 [2,0,0] +} + +// CHECK: _Z5func2ii: +int func2(int a, int b) { + // W_SYS: Decision,File 0, [[@LINE+5]]:11 -> [[@LINE+5]]:28 = M:0, C:3 + // X_SYS: Decision,File 0, [[@LINE+4]]:11 -> [[@LINE+4]]:28 = M:0, C:2 + // W_SYS: Expansion,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:16 = #0 (Expanded file = 1) + // W_SYS: Expansion,File 0, [[@LINE+2]]:23 -> [[@LINE+2]]:28 = #1 (Expanded file = 2) + // X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = #1, (#0 - #1) [1,2,0] + return (EXPR2(a) && EXPR1(a)); + // W_SYS: Branch,File 1, [[@LINE-35]]:19 -> [[@LINE-35]]:22 = #3, (#0 - #3) [1,3,0] + // W_SYS: Branch,File 1, [[@LINE-36]]:26 -> [[@LINE-36]]:29 = #4, (#3 - #4) [3,2,0] + // W_SYS: Branch,File 2, [[@LINE-38]]:18 -> [[@LINE-38]]:21 = #2, (#1 - #2) [2,0,0] + // X_SYS: Branch,File 0, [[@LINE-4]]:23 -> [[@LINE-4]]:23 = #2, (#1 - #2) [2,0,0] +} + +#endif diff --git a/clang/test/Driver/flang/msvc-link.f90 b/clang/test/Driver/flang/msvc-link.f90 new file mode 100644 index 0000000000000000000000000000000000000000..536da2599431f445df49f08e5f6ed4c533106e54 --- /dev/null +++ b/clang/test/Driver/flang/msvc-link.f90 @@ -0,0 +1,5 @@ +! RUN: %clang --driver-mode=flang -target x86_64-pc-windows-msvc -### %s -Ltest 2>&1 | FileCheck %s +! +! Test that user provided paths come before the Flang runtimes +! CHECK: "-libpath:test" +! CHECK: "-libpath:{{.*(\\|/)}}lib" diff --git a/clang/test/Driver/frelaxed-template-template-args.cpp b/clang/test/Driver/frelaxed-template-template-args.cpp index 57fc4e3da6e5d0c46db409d5faf3751e0bf02788..7a7fd6f0bbc8f925a46ecd581ca47ed44432d31f 100644 --- a/clang/test/Driver/frelaxed-template-template-args.cpp +++ b/clang/test/Driver/frelaxed-template-template-args.cpp @@ -1,7 +1,9 @@ // RUN: %clang -fsyntax-only -### %s 2>&1 | FileCheck --check-prefix=CHECK-DEF %s // RUN: %clang -fsyntax-only -frelaxed-template-template-args %s 2>&1 | FileCheck --check-prefix=CHECK-ON %s // RUN: %clang -fsyntax-only -fno-relaxed-template-template-args %s 2>&1 | FileCheck --check-prefix=CHECK-OFF %s +// RUN: %clang -fsyntax-only -fno-relaxed-template-template-args -Wno-deprecated-no-relaxed-template-template-args %s 2>&1 | FileCheck --check-prefix=CHECK-DIS --allow-empty %s // CHECK-DEF-NOT: "-cc1"{{.*}} "-fno-relaxed-template-template-args" // CHECK-ON: warning: argument '-frelaxed-template-template-args' is deprecated [-Wdeprecated] -// CHECK-OFF: warning: argument '-fno-relaxed-template-template-args' is deprecated [-Wdeprecated] +// CHECK-OFF: warning: argument '-fno-relaxed-template-template-args' is deprecated [-Wdeprecated-no-relaxed-template-template-args] +// CHECK-DIS-NOT: warning: argument '-fno-relaxed-template-template-args' is deprecated diff --git a/clang/test/Driver/mips-as.c b/clang/test/Driver/mips-as.c index 14fbb18c93500b8c7deb38525100c226f2978605..a3399f1078fcd6e272dc51f8cd87a04d30d0135d 100644 --- a/clang/test/Driver/mips-as.c +++ b/clang/test/Driver/mips-as.c @@ -266,7 +266,7 @@ // RUN: %clang -target mips-linux-gnu -mno-msa -mmsa -### \ // RUN: -no-integrated-as -fno-pic -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS-MSA %s -// MIPS-MSA: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-mno-shared" "-call_nonpic" "-EB" "-mfpxx" "-mmsa" +// MIPS-MSA: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-mno-shared" "-call_nonpic" "-EB" "-mmsa" // // RUN: %clang -target mips-linux-gnu -mmsa -mno-msa -### \ // RUN: -no-integrated-as -fno-pic -c %s 2>&1 \ diff --git a/clang/test/Driver/mips-features.c b/clang/test/Driver/mips-features.c index 5e92dccaa02abb3aabad977d5344c915129eab44..8b8db4c4a341bb36ee07d4beeced1cefe8a63978 100644 --- a/clang/test/Driver/mips-features.c +++ b/clang/test/Driver/mips-features.c @@ -163,6 +163,12 @@ // RUN: | FileCheck --check-prefix=CHECK-NOMMSA %s // CHECK-NOMMSA: "-target-feature" "-msa" // +// -mmsa +// RUN: %clang -target mips-linux-gnu -### -c %s \ +// RUN: -mmsa 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-MMSA-MFP64 %s +// CHECK-MMSA-MFP64: "-target-feature" "+msa" "-target-feature" "+fp64" +// // -mmt // RUN: %clang -target mips-linux-gnu -### -c %s \ // RUN: -mno-mt -mmt 2>&1 \ diff --git a/clang/test/Driver/ps4-ps5-visibility-dllstorageclass.c b/clang/test/Driver/ps4-ps5-visibility-dllstorageclass.c index 430827805a8fdad1c549446b36d1fe5c4aee772a..71f8661679eb79d24d24d93bd083bcb9ddd944c5 100644 --- a/clang/test/Driver/ps4-ps5-visibility-dllstorageclass.c +++ b/clang/test/Driver/ps4-ps5-visibility-dllstorageclass.c @@ -1,16 +1,19 @@ // Check behaviour of -fvisibility-from-dllstorageclass options for PS4/PS5. // DEFINE: %{triple} = +// DEFINE: %{prefix} = // DEFINE: %{run} = \ // DEFINE: %clang -### -target %{triple} %s -Werror -o - 2>&1 | \ -// DEFINE: FileCheck %s --check-prefix=DEFAULTS \ +// DEFINE: FileCheck %s --check-prefixes=DEFAULTS,%{prefix} \ // DEFINE: --implicit-check-not=-fvisibility-from-dllstorageclass \ // DEFINE: --implicit-check-not=-fvisibility-dllexport \ // DEFINE: --implicit-check-not=-fvisibility-nodllstorageclass \ // DEFINE: --implicit-check-not=-fvisibility-externs-dllimport \ // DEFINE: --implicit-check-not=-fvisibility-externs-nodllstorageclass +// REDEFINE: %{prefix} = DEFAULTS-PS4 // REDEFINE: %{triple} = x86_64-scei-ps4 // RUN: %{run} +// REDEFINE: %{prefix} = DEFAULTS-PS5 // REDEFINE: %{triple} = x86_64-sie-ps5 // RUN: %{run} // @@ -20,25 +23,29 @@ // REDEFINE: -fvisibility-from-dllstorageclass \ // REDEFINE: -Werror \ // REDEFINE: %s -o - 2>&1 | \ -// REDEFINE: FileCheck %s --check-prefix=DEFAULTS \ +// REDEFINE: FileCheck %s --check-prefixes=DEFAULTS,%{prefix} \ // REDEFINE: --implicit-check-not=-fvisibility-from-dllstorageclass \ // REDEFINE: --implicit-check-not=-fvisibility-dllexport \ // REDEFINE: --implicit-check-not=-fvisibility-nodllstorageclass \ // REDEFINE: --implicit-check-not=-fvisibility-externs-dllimport \ // REDEFINE: --implicit-check-not=-fvisibility-externs-nodllstorageclass +// REDEFINE: %{prefix} = DEFAULTS-PS4 // REDEFINE: %{triple} = x86_64-scei-ps4 // RUN: %{run} +// REDEFINE: %{prefix} = DEFAULTS-PS5 // REDEFINE: %{triple} = x86_64-sie-ps5 // RUN: %{run} // DEFAULTS: "-fvisibility-from-dllstorageclass" // DEFAULTS-SAME: "-fvisibility-dllexport=protected" -// DEFAULTS-SAME: "-fvisibility-nodllstorageclass=hidden" +// DEFAULTS-PS4-SAME: "-fvisibility-nodllstorageclass=hidden" +// DEFAULTS-PS5-SAME: "-fvisibility-nodllstorageclass=keep" // DEFAULTS-SAME: "-fvisibility-externs-dllimport=default" -// DEFAULTS-SAME: "-fvisibility-externs-nodllstorageclass=default" +// DEFAULTS-PS4-SAME: "-fvisibility-externs-nodllstorageclass=default" +// DEFAULTS-PS5-SAME: "-fvisibility-externs-nodllstorageclass=keep" // REDEFINE: %{run} = \ -// REDEFINE: %clang -### -target x86_64-scei-ps4 \ +// REDEFINE: %clang -### -target %{triple} \ // REDEFINE: -fvisibility-from-dllstorageclass \ // REDEFINE: -fvisibility-dllexport=hidden \ // REDEFINE: -fvisibility-nodllstorageclass=protected \ @@ -64,37 +71,41 @@ // UNUSED-NEXT: warning: argument unused during compilation: '-fvisibility-externs-nodllstorageclass=protected' // REDEFINE: %{run} = \ -// REDEFINE: %clang -### -target x86_64-scei-ps4 \ +// REDEFINE: %clang -### -target %{triple} \ // REDEFINE: -fvisibility-nodllstorageclass=protected \ // REDEFINE: -fvisibility-externs-dllimport=hidden \ // REDEFINE: -Werror \ // REDEFINE: %s -o - 2>&1 | \ -// REDEFINE: FileCheck %s -check-prefix=SOME \ +// REDEFINE: FileCheck %s -check-prefixes=SOME,%{prefix} \ // REDEFINE: --implicit-check-not=-fvisibility-from-dllstorageclass \ // REDEFINE: --implicit-check-not=-fvisibility-dllexport \ // REDEFINE: --implicit-check-not=-fvisibility-nodllstorageclass \ // REDEFINE: --implicit-check-not=-fvisibility-externs-dllimport \ // REDEFINE: --implicit-check-not=-fvisibility-externs-nodllstorageclass +// REDEFINE: %{prefix} = SOME-PS4 // REDEFINE: %{triple} = x86_64-scei-ps4 // RUN: %{run} +// REDEFINE: %{prefix} = SOME-PS5 // REDEFINE: %{triple} = x86_64-sie-ps5 // RUN: %{run} // REDEFINE: %{run} = \ -// REDEFINE: %clang -### -target x86_64-scei-ps4 \ +// REDEFINE: %clang -### -target %{triple} \ // REDEFINE: -fvisibility-from-dllstorageclass \ // REDEFINE: -fvisibility-nodllstorageclass=protected \ // REDEFINE: -fvisibility-externs-dllimport=hidden \ // REDEFINE: -Werror \ // REDEFINE: %s -o - 2>&1 | \ -// REDEFINE: FileCheck %s -check-prefix=SOME \ +// REDEFINE: FileCheck %s -check-prefixes=SOME,%{prefix} \ // REDEFINE: --implicit-check-not=-fvisibility-from-dllstorageclass \ // REDEFINE: --implicit-check-not=-fvisibility-dllexport \ // REDEFINE: --implicit-check-not=-fvisibility-nodllstorageclass \ // REDEFINE: --implicit-check-not=-fvisibility-externs-dllimport \ // REDEFINE: --implicit-check-not=-fvisibility-externs-nodllstorageclass +// REDEFINE: %{prefix} = SOME-PS4 // REDEFINE: %{triple} = x86_64-scei-ps4 // RUN: %{run} +// REDEFINE: %{prefix} = SOME-PS5 // REDEFINE: %{triple} = x86_64-sie-ps5 // RUN: %{run} @@ -102,10 +113,11 @@ // SOME-SAME: "-fvisibility-dllexport=protected" // SOME-SAME: "-fvisibility-nodllstorageclass=protected" // SOME-SAME: "-fvisibility-externs-dllimport=hidden" -// SOME-SAME: "-fvisibility-externs-nodllstorageclass=default" +// SOME-PS4-SAME: "-fvisibility-externs-nodllstorageclass=default" +// SOME-PS5-SAME: "-fvisibility-externs-nodllstorageclass=keep" // REDEFINE: %{run} = \ -// REDEFINE: %clang -### -target x86_64-scei-ps4 \ +// REDEFINE: %clang -### -target %{triple} \ // REDEFINE: -fvisibility-dllexport=default \ // REDEFINE: -fvisibility-dllexport=hidden \ // REDEFINE: -fvisibility-nodllstorageclass=default \ @@ -121,14 +133,15 @@ // REDEFINE: --implicit-check-not=-fvisibility-dllexport \ // REDEFINE: --implicit-check-not=-fvisibility-nodllstorageclass \ // REDEFINE: --implicit-check-not=-fvisibility-externs-dllimport \ -// REDEFINE: --implicit-check-not=-fvisibility-externs-nodllstorageclass +// REDEFINE: --implicit-check-not=-fvisibility-externs-nodllstorageclass \ +// REDEFINE: --implicit-check-not="warning: argument unused" // REDEFINE: %{triple} = x86_64-scei-ps4 // RUN: %{run} // REDEFINE: %{triple} = x86_64-sie-ps5 // RUN: %{run} // REDEFINE: %{run} = \ -// REDEFINE: %clang -### -target x86_64-scei-ps4 \ +// REDEFINE: %clang -### -target %{triple} \ // REDEFINE: -fvisibility-from-dllstorageclass \ // REDEFINE: -fvisibility-dllexport=default \ // REDEFINE: -fvisibility-dllexport=hidden \ diff --git a/clang/test/Driver/ps4-visibility.cl b/clang/test/Driver/ps4-visibility.cl new file mode 100644 index 0000000000000000000000000000000000000000..a0ed7c71f1f0e5235007ce4813b2cb5574cdf18c --- /dev/null +++ b/clang/test/Driver/ps4-visibility.cl @@ -0,0 +1,32 @@ +/// Check PS4 specific interactions between visibility options. +/// Detailed testing of -fvisibility-from-dllstorageclass is covered elsewhere. + +/// Check defaults. +// RUN: %clang -### -target x86_64-scei-ps4 -x cl -c -emit-llvm %s 2>&1 | \ +// RUN: FileCheck -check-prefix=DEFAULT %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// DEFAULT-DAG: "-fvisibility-from-dllstorageclass" +// DEFAULT-DAG: "-fvisibility-dllexport=protected" +// DEFAULT-DAG: "-fvisibility-nodllstorageclass=hidden" +// DEFAULT-DAG: "-fvisibility-externs-dllimport=default" +// DEFAULT-DAG: "-fvisibility-externs-nodllstorageclass=default" + +/// Check that -fvisibility-from-dllstorageclass is added in the presence of -fvisibility=. +// RUN: %clang -### -target x86_64-scei-ps4 -x cl -c -emit-llvm -fvisibility=default %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=DEFAULT,VISEQUALS %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// VISEQUALS-DAG: "-fvisibility=default" + +/// Check that -fvisibility-from-dllstorageclass is added in the presence of -fvisibility-ms-compat. +// RUN: %clang -### -target x86_64-scei-ps4 -x cl -c -emit-llvm -fvisibility-ms-compat %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=DEFAULT,MSCOMPT %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// MSCOMPT-DAG: "-fvisibility=hidden" +// MSCOMPT-DAG: "-ftype-visibility=default" + +/// -fvisibility-from-dllstorageclass added explicitly. +// RUN: %clang -### -target x86_64-scei-ps4 -x cl -c -emit-llvm -fvisibility-from-dllstorageclass %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=DEFAULT %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass + +/// -fvisibility-from-dllstorageclass disabled explicitly. +// RUN: %clang -### -target x86_64-scei-ps4 -x cl -c -emit-llvm -fno-visibility-from-dllstorageclass %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=NOVISFROM %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// NOVISFROM-NOT: "-fvisibility-from-dllstorageclass" + diff --git a/clang/test/Driver/ps5-visibility.cl b/clang/test/Driver/ps5-visibility.cl new file mode 100644 index 0000000000000000000000000000000000000000..ad144057be63adc5b68390439367694f75c8db3a --- /dev/null +++ b/clang/test/Driver/ps5-visibility.cl @@ -0,0 +1,33 @@ +/// Check PS5 specific interactions between visibility options. +/// Detailed testing of -fvisibility-from-dllstorageclass is covered elsewhere. + +/// Check defaults. +// RUN: %clang -### -target x86_64-sie-ps5 -x cl -c -emit-llvm %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=VDEFAULT,VGND_DEFAULT,DEFAULT %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// VDEFAULT-DAG: "-fvisibility=hidden" +// VGND_DEFAULT-DAG: "-fvisibility-global-new-delete=source" +// DEFAULT-DAG: "-fvisibility-from-dllstorageclass" +// DEFAULT-DAG: "-fvisibility-dllexport=protected" +// DEFAULT-DAG: "-fvisibility-nodllstorageclass=keep" +// DEFAULT-DAG: "-fvisibility-externs-dllimport=default" +// DEFAULT-DAG: "-fvisibility-externs-nodllstorageclass=keep" + +/// -fvisibility= specified explicitly. +// RUN: %clang -### -target x86_64-sie-ps5 -x cl -c -emit-llvm -fvisibility=protected %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=VPROTECTED,VGND_DEFAULT,DEFAULT %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// VPROTECTED-DAG: "-fvisibility=protected" + +/// -fvisibility-ms-compat added explicitly. +// RUN: %clang -### -target x86_64-sie-ps5 -x cl -c -emit-llvm -fvisibility-ms-compat %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=MSCOMPT,VGND_DEFAULT,DEFAULT %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// MSCOMPT-DAG: "-fvisibility=hidden" +// MSCOMPT-DAG: "-ftype-visibility=default" + +/// -fvisibility-from-dllstorageclass added explicitly. +// RUN: %clang -### -target x86_64-sie-ps5 -x cl -c -emit-llvm -fvisibility-from-dllstorageclass %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=VDEFAULT,VGND_DEFAULT,DEFAULT %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass + +/// -fvisibility-from-dllstorageclass disabled explicitly. +// RUN: %clang -### -target x86_64-sie-ps5 -x cl -c -emit-llvm -fno-visibility-from-dllstorageclass %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=VDEFAULT,VGND_DEFAULT,NOVISFROM %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// NOVISFROM-NOT: "-fvisibility-from-dllstorageclass" diff --git a/clang/test/Driver/riscv-profiles.c b/clang/test/Driver/riscv-profiles.c index 298f301de3feb621d3ce227cec05a564e33a459d..55aa5b398cee98d2ae7c17595b1470e46ef8ed3a 100644 --- a/clang/test/Driver/riscv-profiles.c +++ b/clang/test/Driver/riscv-profiles.c @@ -111,7 +111,7 @@ // RVA22S64: "-target-feature" "+svinval" // RVA22S64: "-target-feature" "+svpbmt" -// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rva23u64 \ +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rva23u64 -menable-experimental-extensions \ // RUN: | FileCheck -check-prefix=RVA23U64 %s // RVA23U64: "-target-feature" "+m" // RVA23U64: "-target-feature" "+a" @@ -207,7 +207,7 @@ // RVA23S64: "-target-feature" "+svnapot" // RVA23S64: "-target-feature" "+svpbmt" -// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rvb23u64 \ +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rvb23u64 -menable-experimental-extensions \ // RUN: | FileCheck -check-prefix=RVB23U64 %s // RVB23U64: "-target-feature" "+m" // RVB23U64: "-target-feature" "+a" @@ -284,7 +284,7 @@ // RVB23S64: "-target-feature" "+svnapot" // RVB23S64: "-target-feature" "+svpbmt" -// RUN: %clang --target=riscv32 -### -c %s 2>&1 -march=rvm23u32 \ +// RUN: %clang --target=riscv32 -### -c %s 2>&1 -march=rvm23u32 -menable-experimental-extensions \ // RUN: | FileCheck -check-prefix=RVM23U32 %s // RVM23U32: "-target-feature" "+m" // RVM23U32: "-target-feature" "+zicbop" @@ -322,3 +322,7 @@ // RUN: not %clang --target=riscv64 -### -c %s 2>&1 -march=rva22u64zfa | FileCheck -check-prefix=INVALID-ADDITIONAL %s // INVALID-ADDITIONAL: error: invalid arch name 'rva22u64zfa', additional extensions must be after separator '_' + +// RUN: not %clang --target=riscv64 -### -c %s 2>&1 -march=rva23u64 | FileCheck -check-prefix=EXPERIMENTAL-NOFLAG %s +// EXPERIMENTAL-NOFLAG: error: invalid arch name 'rva23u64' +// EXPERIMENTAL-NOFLAG: requires '-menable-experimental-extensions' for profile 'rva23u64' diff --git a/clang/test/ExtractAPI/class_template.cpp b/clang/test/ExtractAPI/class_template.cpp index 4f2670d7b6997721f9937b8c5147e82ea456240f..203d47394dd60d95f1bc1967ea33bc13148ae524 100644 --- a/clang/test/ExtractAPI/class_template.cpp +++ b/clang/test/ExtractAPI/class_template.cpp @@ -51,7 +51,7 @@ template class Foo {}; }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", diff --git a/clang/test/ExtractAPI/class_template_param_inheritance.cpp b/clang/test/ExtractAPI/class_template_param_inheritance.cpp index 3d7b09f93ed6de35cd8655f8ce4d903d5c99ee12..53b331e0b460be8fb698a34943c12ded2f4d8c2a 100644 --- a/clang/test/ExtractAPI/class_template_param_inheritance.cpp +++ b/clang/test/ExtractAPI/class_template_param_inheritance.cpp @@ -58,7 +58,7 @@ template class Foo : public T {}; }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", diff --git a/clang/test/ExtractAPI/class_template_partial_spec.cpp b/clang/test/ExtractAPI/class_template_partial_spec.cpp index c8d9cc78d41c5ce70cb30f1ad6750584b37aae0a..7d244f49c735965757b714701a1788b0b3b21008 100644 --- a/clang/test/ExtractAPI/class_template_partial_spec.cpp +++ b/clang/test/ExtractAPI/class_template_partial_spec.cpp @@ -53,7 +53,7 @@ template class Foo {}; }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", @@ -161,7 +161,7 @@ template class Foo {}; }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", diff --git a/clang/test/ExtractAPI/class_template_spec.cpp b/clang/test/ExtractAPI/class_template_spec.cpp index 06a95314dc4aa0804e5e23cbac9d429147c35345..9dbd887510c70cf4deb484d2bc9df933952773d7 100644 --- a/clang/test/ExtractAPI/class_template_spec.cpp +++ b/clang/test/ExtractAPI/class_template_spec.cpp @@ -53,7 +53,7 @@ template<> class Foo {}; }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", @@ -140,7 +140,7 @@ template<> class Foo {}; }, { "kind": "text", - "spelling": "<> " + "spelling": " <> " }, { "kind": "keyword", diff --git a/clang/test/ExtractAPI/concept.cpp b/clang/test/ExtractAPI/concept.cpp index 443eac2971f0e5471988fc76a2e49a3b7eb39a65..4396a39a63ef6d7ee06cef5c886e3df8eeff997c 100644 --- a/clang/test/ExtractAPI/concept.cpp +++ b/clang/test/ExtractAPI/concept.cpp @@ -51,7 +51,7 @@ template concept Foo = true; }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", diff --git a/clang/test/ExtractAPI/field_template.cpp b/clang/test/ExtractAPI/field_template.cpp index 2058ed008cfe40e5861f1d40bb87d5249490ad6f..973a9de5c9986b572155f1dbcba06825d6f6b031 100644 --- a/clang/test/ExtractAPI/field_template.cpp +++ b/clang/test/ExtractAPI/field_template.cpp @@ -114,7 +114,7 @@ class Foo { }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", diff --git a/clang/test/ExtractAPI/global_func_template.cpp b/clang/test/ExtractAPI/global_func_template.cpp index f43a618ec0c366f5480ab1672f56eb74dc1b915e..044757c316d58b172dc8bdf87e00c16a00702f8b 100644 --- a/clang/test/ExtractAPI/global_func_template.cpp +++ b/clang/test/ExtractAPI/global_func_template.cpp @@ -52,7 +52,7 @@ template T Fizz(int Buzz); }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", @@ -186,7 +186,7 @@ template T Fizz(int Buzz); }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", diff --git a/clang/test/ExtractAPI/global_func_template_spec.cpp b/clang/test/ExtractAPI/global_func_template_spec.cpp index fe046e9c3b9dac277700baab5bf4d9f3490de3e8..b88063aacfedce9b6952670c216bbc636d662db5 100644 --- a/clang/test/ExtractAPI/global_func_template_spec.cpp +++ b/clang/test/ExtractAPI/global_func_template_spec.cpp @@ -52,7 +52,7 @@ template<> void Foo(int Bar); }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", @@ -186,7 +186,7 @@ template<> void Foo(int Bar); }, { "kind": "text", - "spelling": "<> " + "spelling": " <> " }, { "kind": "typeIdentifier", diff --git a/clang/test/ExtractAPI/global_var_template.cpp b/clang/test/ExtractAPI/global_var_template.cpp index 94f3713cd3d31b5e421efa4499252ba2a1b41a40..5c9194141332bbb246e8b72a3ba96fe6e58667aa 100644 --- a/clang/test/ExtractAPI/global_var_template.cpp +++ b/clang/test/ExtractAPI/global_var_template.cpp @@ -50,7 +50,7 @@ template T Foo = T(3.14); }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", diff --git a/clang/test/ExtractAPI/global_var_template_partial_spec.cpp b/clang/test/ExtractAPI/global_var_template_partial_spec.cpp index 91084f258878ee704b2d41e5d51d12d6f50b1de5..ffb1557fd7580065cb92aa67696a0577a8592a34 100644 --- a/clang/test/ExtractAPI/global_var_template_partial_spec.cpp +++ b/clang/test/ExtractAPI/global_var_template_partial_spec.cpp @@ -52,7 +52,7 @@ template int Foo = 0; }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", @@ -161,7 +161,7 @@ template int Foo = 0; }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", diff --git a/clang/test/ExtractAPI/global_var_template_spec.cpp b/clang/test/ExtractAPI/global_var_template_spec.cpp index ff4d8d17aecbe9c0576a5482c399f3a0064f8d46..e465da97db1f22c81278a034ef053280f2b375a8 100644 --- a/clang/test/ExtractAPI/global_var_template_spec.cpp +++ b/clang/test/ExtractAPI/global_var_template_spec.cpp @@ -52,7 +52,7 @@ template<> int Foo; }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", @@ -140,7 +140,7 @@ template<> int Foo; }, { "kind": "text", - "spelling": "<> " + "spelling": " <> " }, { "kind": "typeIdentifier", diff --git a/clang/test/ExtractAPI/method_template.cpp b/clang/test/ExtractAPI/method_template.cpp index 714f9cac26c208a8c354c0fc672f0a2a7b6e5fb0..bf91a208c54884fa4b4e2c615d582f82cd391332 100644 --- a/clang/test/ExtractAPI/method_template.cpp +++ b/clang/test/ExtractAPI/method_template.cpp @@ -114,7 +114,7 @@ class Foo { }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", diff --git a/clang/test/ExtractAPI/method_template_spec.cpp b/clang/test/ExtractAPI/method_template_spec.cpp index 8eaffdefd827a91476f755564f92cf7454e5a6e2..978dbe1b6c1d66d3bcd596fabe635219784a1b7a 100644 --- a/clang/test/ExtractAPI/method_template_spec.cpp +++ b/clang/test/ExtractAPI/method_template_spec.cpp @@ -122,7 +122,7 @@ class Foo { }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", @@ -257,7 +257,7 @@ class Foo { }, { "kind": "text", - "spelling": "<> " + "spelling": " <> " }, { "kind": "typeIdentifier", diff --git a/clang/test/ExtractAPI/non_type_template.cpp b/clang/test/ExtractAPI/non_type_template.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4e65eb790ca113d605225f3dfae7427d6ebbca47 --- /dev/null +++ b/clang/test/ExtractAPI/non_type_template.cpp @@ -0,0 +1,313 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: -triple arm64-apple-macosx -std=c++17 -x c++-header %s -o %t/output.symbols.json -verify + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix FOO +template class Foo { }; +// FOO-LABEL: "!testLabel": "c:@ST>2#T#NI@Foo" +// FOO: "declarationFragments": [ +// FOO-NEXT: { +// FOO-NEXT: "kind": "keyword", +// FOO-NEXT: "spelling": "template" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "text", +// FOO-NEXT: "spelling": " <" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "keyword", +// FOO-NEXT: "spelling": "typename" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "text", +// FOO-NEXT: "spelling": " " +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "genericParameter", +// FOO-NEXT: "spelling": "T" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "text", +// FOO-NEXT: "spelling": ", " +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "typeIdentifier", +// FOO-NEXT: "preciseIdentifier": "c:I", +// FOO-NEXT: "spelling": "int" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "text", +// FOO-NEXT: "spelling": " " +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "genericParameter", +// FOO-NEXT: "spelling": "N" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "text", +// FOO-NEXT: "spelling": " = 4> " +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "keyword", +// FOO-NEXT: "spelling": "class" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "text", +// FOO-NEXT: "spelling": " " +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "identifier", +// FOO-NEXT: "spelling": "Foo" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "text", +// FOO-NEXT: "spelling": ";" +// FOO-NEXT: } +// FOO-NEXT: ] + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix FOO-SPEC +template class Foo { }; +// FOO-SPEC-LABEL: "!testLabel": "c:@SP>1#T@Foo>#t0.0#VI4" +// FOO-SPEC: "declarationFragments": [ +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "keyword", +// FOO-SPEC-NEXT: "spelling": "template" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "text", +// FOO-SPEC-NEXT: "spelling": " <" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "keyword", +// FOO-SPEC-NEXT: "spelling": "typename" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "text", +// FOO-SPEC-NEXT: "spelling": " " +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "genericParameter", +// FOO-SPEC-NEXT: "spelling": "T" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "text", +// FOO-SPEC-NEXT: "spelling": "> " +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "keyword", +// FOO-SPEC-NEXT: "spelling": "class" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "text", +// FOO-SPEC-NEXT: "spelling": " " +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "identifier", +// FOO-SPEC-NEXT: "spelling": "Foo" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "text", +// FOO-SPEC-NEXT: "spelling": "<" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "typeIdentifier", +// FOO-SPEC-NEXT: "preciseIdentifier": "c:t0.0", +// FOO-SPEC-NEXT: "spelling": "T" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "text", +// FOO-SPEC-NEXT: "spelling": ", 4>;" +// FOO-SPEC-NEXT: } +// FOO-SPEC-NEXT: ] + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix NEST +template