diff --git a/.ci/generate-buildkite-pipeline-premerge b/.ci/generate-buildkite-pipeline-premerge index 4ebf304e23d5875c23d626984d17fb1ed5004a0f..c14ec464a43a666830dbc2bcace663e5baec3d7a 100755 --- a/.ci/generate-buildkite-pipeline-premerge +++ b/.ci/generate-buildkite-pipeline-premerge @@ -233,7 +233,10 @@ linux_projects=$(add-dependencies ${linux_projects_to_test} | sort | uniq) windows_projects_to_test=$(exclude-windows $(compute-projects-to-test ${modified_projects})) windows_check_targets=$(check-targets ${windows_projects_to_test} | sort | uniq) -windows_projects=$(add-dependencies ${windows_projects_to_test} | sort | uniq) +# Temporary disable the windows job. +# See https://discourse.llvm.org/t/rfc-future-of-windows-pre-commit-ci/76840 +#windows_projects=$(add-dependencies ${windows_projects_to_test} | sort | uniq) +windows_projects="" # Generate the appropriate pipeline if [[ "${linux_projects}" != "" ]]; then diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index ea84e31a6fa9898e505e27743350ef67ef196ba6..1f498a8be943c40670a235cbde3a3485ddb7e95a 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -78,3 +78,6 @@ f6d557ee34b6bbdb1dc32f29e34b4a4a8ad35e81 082b89b25faae3e45a023caf51b65ca0f02f377f 0ba22f51d128bee9d69756c56c4678097270e10b 84da0e1bb75f8666cf222d2f600f37bebb9ea389 + +# [NFC] clang-format utils/TableGen (#80973) +b9079baaddfed5e604fbfaa1d81a7a1c38e78c26 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 767f58e01a395654c3681492007b0e5cd89e463e..3fe0cbbcb84d2900d2a16af83b05fe0c462d707e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -103,4 +103,4 @@ /mlir/**/*SparseTensor*/ @aartbik @PeimingLiu @yinying-lisa-li @matthias-springer # BOLT -/bolt/ @aaupov @maksfb @rafaelauler @dcci +/bolt/ @aaupov @maksfb @rafaelauler @ayermolo @dcci diff --git a/.github/workflows/approved-prs.yml b/.github/workflows/approved-prs.yml new file mode 100644 index 0000000000000000000000000000000000000000..309a9217e42d31eddbdd65df3eb14dd336e3474b --- /dev/null +++ b/.github/workflows/approved-prs.yml @@ -0,0 +1,39 @@ +name: "Prompt reviewers to merge PRs on behalf of authors" + +permissions: + contents: read + +on: + pull_request_review: + types: + - submitted + +jobs: + merge-on-behalf-information-comment: + runs-on: ubuntu-latest + permissions: + pull-requests: write + if: >- + (github.repository == 'llvm/llvm-project') && + (github.event.review.state == 'APPROVED') + steps: + - name: Checkout Automation Script + uses: actions/checkout@v4 + with: + sparse-checkout: llvm/utils/git/ + ref: main + + - name: Setup Automation Script + working-directory: ./llvm/utils/git/ + run: | + pip install -r requirements.txt + + - name: Add Merge On Behalf Comment + working-directory: ./llvm/utils/git/ + run: | + python3 ./github-automation.py \ + --token '${{ secrets.GITHUB_TOKEN }}' \ + pr-merge-on-behalf-information \ + --issue-number "${{ github.event.pull_request.number }}" \ + --author "${{ github.event.pull_request.user.login }}" \ + --reviewer "${{ github.event.review.user.login }}" diff --git a/.github/workflows/issue-release-workflow.yml b/.github/workflows/issue-release-workflow.yml index 33a1e89a729f6b13ddda2733f7793dacad858496..448c1c56f897f5ef99aa9877fb30dd8c5603a3f9 100644 --- a/.github/workflows/issue-release-workflow.yml +++ b/.github/workflows/issue-release-workflow.yml @@ -65,4 +65,5 @@ jobs: release-workflow \ --branch-repo-token ${{ secrets.RELEASE_WORKFLOW_PUSH_SECRET }} \ --issue-number ${{ github.event.issue.number }} \ + --requested-by ${{ github.event.issue.user.login }} \ auto diff --git a/.github/workflows/llvm-project-workflow-tests.yml b/.github/workflows/llvm-project-workflow-tests.yml new file mode 100644 index 0000000000000000000000000000000000000000..a2539b279be0a067d7b2b2bd3b5d7ff638c861f8 --- /dev/null +++ b/.github/workflows/llvm-project-workflow-tests.yml @@ -0,0 +1,32 @@ +# This workflow will test the llvm-project-tests workflow in PRs +# targetting the main branch. Since this workflow doesn't normally +# run on main PRs, we need some way to test it to ensure new updates +# don't break it. + +name: LLVM Workflow Test + +permissions: + contents: read + +on: + pull_request: + branches: + - 'main' + paths: + - '.github/workflows/llvm-project-tests.yml' + - '.github/workflows/llvm-project-workflow-tests.yml' + +concurrency: + # Skip intermediate builds: always. + # Cancel intermediate builds: only if it is a pull request build. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} + +jobs: + llvm-test: + if: github.repository_owner == 'llvm' + name: Build and Test + uses: ./.github/workflows/llvm-project-tests.yml + with: + build_target: check-all + projects: clang;lld;libclc;lldb diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h index f1db1fbded6a470ba02bf3c582c973f8f99fc3c3..30336c4e3a74fee2ac1d72175f04b40f019c7746 100644 --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -145,6 +145,35 @@ public: } }; +/// BOLT-exclusive errors generated in core BOLT libraries, optionally holding a +/// string message and whether it is fatal or not. In case it is fatal and if +/// BOLT is running as a standalone process, the process might be killed as soon +/// as the error is checked. +class BOLTError : public ErrorInfo { +public: + static char ID; + + BOLTError(bool IsFatal, const Twine &S = Twine()); + void log(raw_ostream &OS) const override; + bool isFatal() const { return IsFatal; } + + const std::string &getMessage() const { return Msg; } + std::error_code convertToErrorCode() const override; + +private: + bool IsFatal; + std::string Msg; +}; + +/// Streams used by BOLT to log regular or error events +struct JournalingStreams { + raw_ostream &Out; + raw_ostream &Err; +}; + +Error createNonFatalBOLTError(const Twine &S); +Error createFatalBOLTError(const Twine &S); + class BinaryContext { BinaryContext() = delete; @@ -237,7 +266,8 @@ class BinaryContext { public: static Expected> createBinaryContext(const ObjectFile *File, bool IsPIC, - std::unique_ptr DwCtx); + std::unique_ptr DwCtx, + JournalingStreams Logger); /// Superset of compiler units that will contain overwritten code that needs /// new debug info. In a few cases, functions may end up not being @@ -605,6 +635,10 @@ public: std::unique_ptr MAB; + /// Allows BOLT to print to log whenever it is necessary (with or without + /// const references) + mutable JournalingStreams Logger; + /// Indicates if the binary is Linux kernel. bool IsLinuxKernel{false}; @@ -737,7 +771,8 @@ public: std::unique_ptr MIA, std::unique_ptr MIB, std::unique_ptr MRI, - std::unique_ptr DisAsm); + std::unique_ptr DisAsm, + JournalingStreams Logger); ~BinaryContext(); @@ -1349,8 +1384,12 @@ public: return Offset; } - void exitWithBugReport(StringRef Message, - const BinaryFunction &Function) const; + /// Log BOLT errors to journaling streams and quit process with non-zero error + /// code 1 if error is fatal. + void logBOLTErrorsAndQuitOnFatal(Error E); + + std::string generateBugReportMessage(StringRef Message, + const BinaryFunction &Function) const; struct IndependentCodeEmitter { std::unique_ptr LocalMOFI; @@ -1398,6 +1437,10 @@ public: assert(IOAddressMap && "Address map not set yet"); return *IOAddressMap; } + + raw_ostream &outs() const { return Logger.Out; } + + raw_ostream &errs() const { return Logger.Err; } }; template > diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h index 3a1eae3311bd7623d1263d7627720259e28f83ca..a177178769e4567b15383e071ef5fd67ed62ff99 100644 --- a/bolt/include/bolt/Core/BinaryFunction.h +++ b/bolt/include/bolt/Core/BinaryFunction.h @@ -1910,12 +1910,11 @@ public: /// Support dynamic relocations in constant islands, which may happen if /// binary is linked with -z notext option. - void markIslandDynamicRelocationAtAddress(uint64_t Address) { - if (!isInConstantIsland(Address)) { - errs() << "BOLT-ERROR: dynamic relocation found for text section at 0x" - << Twine::utohexstr(Address) << "\n"; - exit(1); - } + Error markIslandDynamicRelocationAtAddress(uint64_t Address) { + if (!isInConstantIsland(Address)) + return createFatalBOLTError( + Twine("dynamic relocation found for text section at 0x") + + Twine::utohexstr(Address) + Twine("\n")); // Mark island to have dynamic relocation Islands->HasDynamicRelocations = true; @@ -1924,6 +1923,7 @@ public: // move binary data during updateOutputValues, making us emit // dynamic relocation with the right offset value. getOrCreateIslandAccess(Address); + return Error::success(); } bool hasDynamicRelocationAtIsland() const { @@ -2054,9 +2054,10 @@ public: /// state to State:Disassembled. /// /// Returns false if disassembly failed. - bool disassemble(); + Error disassemble(); - void handlePCRelOperand(MCInst &Instruction, uint64_t Address, uint64_t Size); + Error handlePCRelOperand(MCInst &Instruction, uint64_t Address, + uint64_t Size); MCSymbol *handleExternalReference(MCInst &Instruction, uint64_t Size, uint64_t Offset, uint64_t TargetAddress, @@ -2100,7 +2101,7 @@ public: /// /// Returns true on success and update the current function state to /// State::CFG. Returns false if CFG cannot be built. - bool buildCFG(MCPlusBuilder::AllocatorIdTy); + Error buildCFG(MCPlusBuilder::AllocatorIdTy); /// Perform post-processing of the CFG. void postProcessCFG(); @@ -2217,7 +2218,7 @@ public: } /// Process LSDA information for the function. - void parseLSDA(ArrayRef LSDAData, uint64_t LSDAAddress); + Error parseLSDA(ArrayRef LSDAData, uint64_t LSDAAddress); /// Update exception handling ranges for the function. void updateEHRanges(); diff --git a/bolt/include/bolt/Core/BinarySection.h b/bolt/include/bolt/Core/BinarySection.h index 70914f59157d24ef05e812c9372fba409eb81d1a..a85dbf28950e316d5bcbf9870f4759a8e469e0c5 100644 --- a/bolt/include/bolt/Core/BinarySection.h +++ b/bolt/include/bolt/Core/BinarySection.h @@ -112,7 +112,7 @@ class BinarySection { static StringRef getName(SectionRef Section) { return cantFail(Section.getName()); } - static StringRef getContents(SectionRef Section) { + static StringRef getContentsOrQuit(SectionRef Section) { if (Section.getObject()->isELF() && ELFSectionRef(Section).getType() == ELF::SHT_NOBITS) return StringRef(); @@ -159,7 +159,7 @@ public: BinarySection(BinaryContext &BC, SectionRef Section) : BC(BC), Name(getName(Section)), Section(Section), - Contents(getContents(Section)), Address(Section.getAddress()), + Contents(getContentsOrQuit(Section)), Address(Section.getAddress()), Size(Section.getSize()), Alignment(Section.getAlignment().value()), OutputName(Name), SectionNumber(++Count) { if (isELF()) { diff --git a/bolt/include/bolt/Core/DIEBuilder.h b/bolt/include/bolt/Core/DIEBuilder.h index f89084065aae1c45157e6ad9b78bf12af851c5f0..f13d42ff4ab42afdb185e6e483e4475c4aa11735 100644 --- a/bolt/include/bolt/Core/DIEBuilder.h +++ b/bolt/include/bolt/Core/DIEBuilder.h @@ -15,6 +15,7 @@ #ifndef BOLT_CORE_DIE_BUILDER_H #define BOLT_CORE_DIE_BUILDER_H +#include "bolt/Core/BinaryContext.h" #include "llvm/CodeGen/DIE.h" #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" @@ -32,6 +33,7 @@ namespace llvm { namespace bolt { + class DIEStreamer; class DebugStrOffsetsWriter; @@ -120,6 +122,7 @@ private: std::unique_ptr BuilderState; FoldingSet AbbreviationsSet; std::vector> Abbreviations; + BinaryContext &BC; DWARFContext *DwarfContext{nullptr}; bool IsDWO{false}; uint64_t UnitSize{0}; @@ -219,9 +222,10 @@ private: if (getState().CloneUnitCtxMap[UnitId].DieInfoVector.size() > DIEId) return *getState().CloneUnitCtxMap[UnitId].DieInfoVector[DIEId].get(); - errs() << "BOLT-WARNING: [internal-dwarf-error]: The DIE is not allocated " - "before looking up, some" - << "unexpected corner cases happened.\n"; + BC.errs() + << "BOLT-WARNING: [internal-dwarf-error]: The DIE is not allocated " + "before looking up, some" + << "unexpected corner cases happened.\n"; return *getState().CloneUnitCtxMap[UnitId].DieInfoVector.front().get(); } @@ -261,7 +265,7 @@ private: DIE *constructDIEFast(DWARFDie &DDie, DWARFUnit &U, uint32_t UnitId); public: - DIEBuilder(DWARFContext *DwarfContext, bool IsDWO = false); + DIEBuilder(BinaryContext &BC, DWARFContext *DwarfContext, bool IsDWO = false); /// Returns enum to what we are currently processing. ProcessingType getCurrentProcessingState() { return getState().Type; } @@ -295,8 +299,9 @@ public: if (getState().TypeDIEMap.count(&DU)) return getState().TypeDIEMap[&DU]; - errs() << "BOLT-ERROR: unable to find TypeUnit for Type Unit at offset 0x" - << DU.getOffset() << "\n"; + BC.errs() + << "BOLT-ERROR: unable to find TypeUnit for Type Unit at offset 0x" + << DU.getOffset() << "\n"; return nullptr; } diff --git a/bolt/include/bolt/Core/DynoStats.h b/bolt/include/bolt/Core/DynoStats.h index 65256719ba06bdf2d0668404c605ca1c5ea01aa0..82a69668385b6028af23e17b20680539fc6e1238 100644 --- a/bolt/include/bolt/Core/DynoStats.h +++ b/bolt/include/bolt/Core/DynoStats.h @@ -159,8 +159,9 @@ inline DynoStats getDynoStats(FuncsType &Funcs, bool IsAArch64) { /// Call a function with optional before and after dynostats printing. template -inline void callWithDynoStats(FnType &&Func, FuncsType &Funcs, StringRef Phase, - const bool Flag, bool IsAArch64) { +inline void callWithDynoStats(raw_ostream &OS, FnType &&Func, FuncsType &Funcs, + StringRef Phase, const bool Flag, + bool IsAArch64) { DynoStats DynoStatsBefore(IsAArch64); if (Flag) DynoStatsBefore = getDynoStats(Funcs, IsAArch64); @@ -170,12 +171,12 @@ inline void callWithDynoStats(FnType &&Func, FuncsType &Funcs, StringRef Phase, if (Flag) { const DynoStats DynoStatsAfter = getDynoStats(Funcs, IsAArch64); const bool Changed = (DynoStatsAfter != DynoStatsBefore); - outs() << "BOLT-INFO: program-wide dynostats after running " << Phase - << (Changed ? "" : " (no change)") << ":\n\n" - << DynoStatsBefore << '\n'; + OS << "BOLT-INFO: program-wide dynostats after running " << Phase + << (Changed ? "" : " (no change)") << ":\n\n" + << DynoStatsBefore << '\n'; if (Changed) - DynoStatsAfter.print(outs(), &DynoStatsBefore); - outs() << '\n'; + DynoStatsAfter.print(OS, &DynoStatsBefore); + OS << '\n'; } } diff --git a/bolt/include/bolt/Core/Exceptions.h b/bolt/include/bolt/Core/Exceptions.h index 7c09b5b768fe84e964d51a405577fa0a61dc3f32..422b86f6ddb7a3ac5709cb2644c034526b1626e2 100644 --- a/bolt/include/bolt/Core/Exceptions.h +++ b/bolt/include/bolt/Core/Exceptions.h @@ -30,13 +30,14 @@ class FDE; namespace bolt { +class BinaryContext; class BinaryFunction; /// \brief Wraps up information to read all CFI instructions and feed them to a /// BinaryFunction, as well as rewriting CFI sections. class CFIReaderWriter { public: - explicit CFIReaderWriter(const DWARFDebugFrame &EHFrame); + explicit CFIReaderWriter(BinaryContext &BC, const DWARFDebugFrame &EHFrame); bool fillCFIInfoFor(BinaryFunction &Function) const; @@ -59,6 +60,7 @@ public: const FDEsMap &getFDEs() const { return FDEs; } private: + BinaryContext &BC; FDEsMap FDEs; }; diff --git a/bolt/include/bolt/Passes/ADRRelaxationPass.h b/bolt/include/bolt/Passes/ADRRelaxationPass.h index a5ff0c4a800301685c03a9e3e72df8fe6265e4fd..1d35a335c0250c4a38e84d814d2f0107e9c3e2e3 100644 --- a/bolt/include/bolt/Passes/ADRRelaxationPass.h +++ b/bolt/include/bolt/Passes/ADRRelaxationPass.h @@ -30,7 +30,7 @@ public: const char *getName() const override { return "adr-relaxation"; } /// Pass entry point - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; void runOnFunction(BinaryFunction &BF); }; diff --git a/bolt/include/bolt/Passes/Aligner.h b/bolt/include/bolt/Passes/Aligner.h index 4cb44fdb121e8603e46ee4e2ce78b883ba237d25..eb077182c9456a98cd5df819fce43ce6c2e5cfea 100644 --- a/bolt/include/bolt/Passes/Aligner.h +++ b/bolt/include/bolt/Passes/Aligner.h @@ -39,7 +39,7 @@ public: const char *getName() const override { return "aligner"; } /// Pass entry point - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/AllocCombiner.h b/bolt/include/bolt/Passes/AllocCombiner.h index 44c6fddd34de45b8d38a77d4c278145618d445ae..8532f761c9adb226267c0d1611b2164b73cb4bb8 100644 --- a/bolt/include/bolt/Passes/AllocCombiner.h +++ b/bolt/include/bolt/Passes/AllocCombiner.h @@ -33,7 +33,7 @@ public: } /// Pass entry point - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/AsmDump.h b/bolt/include/bolt/Passes/AsmDump.h index 7cc96f20a92068caaba159387ad17d464f9b4f18..d993909f2794613fe8fb03bb29c14a5347df3814 100644 --- a/bolt/include/bolt/Passes/AsmDump.h +++ b/bolt/include/bolt/Passes/AsmDump.h @@ -28,7 +28,7 @@ public: bool shouldPrint(const BinaryFunction &BF) const override { return false; } /// Pass entry point - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/BinaryPasses.h b/bolt/include/bolt/Passes/BinaryPasses.h index dace07e903e7bc92f6bd59e24809e45017351745..046765b16f19d21b8562440f51c1b0c3c666995e 100644 --- a/bolt/include/bolt/Passes/BinaryPasses.h +++ b/bolt/include/bolt/Passes/BinaryPasses.h @@ -50,8 +50,7 @@ public: /// this pass is completed (printPass() must have returned true). virtual bool shouldPrint(const BinaryFunction &BF) const; - /// Execute this pass on the given functions. - virtual void runOnFunctions(BinaryContext &BC) = 0; + virtual Error runOnFunctions(BinaryContext &BC) = 0; }; /// A pass to print program-wide dynostats. @@ -70,18 +69,19 @@ public: bool shouldPrint(const BinaryFunction &BF) const override { return false; } - void runOnFunctions(BinaryContext &BC) override { + Error runOnFunctions(BinaryContext &BC) override { const DynoStats NewDynoStats = getDynoStats(BC.getBinaryFunctions(), BC.isAArch64()); const bool Changed = (NewDynoStats != PrevDynoStats); - outs() << "BOLT-INFO: program-wide dynostats " << Title - << (Changed ? "" : " (no change)") << ":\n\n" - << PrevDynoStats; + BC.outs() << "BOLT-INFO: program-wide dynostats " << Title + << (Changed ? "" : " (no change)") << ":\n\n" + << PrevDynoStats; if (Changed) { - outs() << '\n'; - NewDynoStats.print(outs(), &PrevDynoStats, BC.InstPrinter.get()); + BC.outs() << '\n'; + NewDynoStats.print(BC.outs(), &PrevDynoStats, BC.InstPrinter.get()); } - outs() << '\n'; + BC.outs() << '\n'; + return Error::success(); } }; @@ -100,7 +100,7 @@ public: const char *getName() const override { return "normalize CFG"; } - void runOnFunctions(BinaryContext &) override; + Error runOnFunctions(BinaryContext &) override; }; /// Detect and eliminate unreachable basic blocks. We could have those @@ -119,7 +119,7 @@ public: bool shouldPrint(const BinaryFunction &BF) const override { return BinaryFunctionPass::shouldPrint(BF) && Modified.count(&BF) > 0; } - void runOnFunctions(BinaryContext &) override; + Error runOnFunctions(BinaryContext &) override; }; // Reorder the basic blocks for each function based on hotness. @@ -165,7 +165,7 @@ public: const char *getName() const override { return "reorder-blocks"; } bool shouldPrint(const BinaryFunction &BF) const override; - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// Sync local branches with CFG. @@ -175,7 +175,7 @@ public: : BinaryFunctionPass(PrintPass) {} const char *getName() const override { return "fix-branches"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// Fix the CFI state and exception handling information after all other @@ -186,7 +186,7 @@ public: : BinaryFunctionPass(PrintPass) {} const char *getName() const override { return "finalize-functions"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// Perform any necessary adjustments for functions that do not fit into their @@ -198,7 +198,7 @@ public: const char *getName() const override { return "check-large-functions"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; bool shouldOptimize(const BinaryFunction &BF) const override; }; @@ -210,7 +210,7 @@ public: : BinaryFunctionPass(PrintPass) {} const char *getName() const override { return "lower-annotations"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// Clean the state of the MC representation before sending it to emission @@ -220,7 +220,7 @@ public: : BinaryFunctionPass(PrintPass) {} const char *getName() const override { return "clean-mc-state"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// An optimization to simplify conditional tail calls by removing @@ -292,7 +292,7 @@ public: bool shouldPrint(const BinaryFunction &BF) const override { return BinaryFunctionPass::shouldPrint(BF) && Modified.count(&BF) > 0; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// Convert instructions to the form with the minimum operand width. @@ -305,7 +305,7 @@ public: const char *getName() const override { return "shorten-instructions"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// Perform simple peephole optimizations. @@ -339,7 +339,7 @@ public: : BinaryFunctionPass(PrintPass) {} const char *getName() const override { return "peepholes"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// An optimization to simplify loads from read-only sections.The pass converts @@ -370,7 +370,7 @@ public: bool shouldPrint(const BinaryFunction &BF) const override { return BinaryFunctionPass::shouldPrint(BF) && Modified.count(&BF) > 0; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// Assign output sections to all functions. @@ -379,7 +379,7 @@ public: explicit AssignSections() : BinaryFunctionPass(false) {} const char *getName() const override { return "assign-sections"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// Compute and report to the user the imbalance in flow equations for all @@ -394,7 +394,7 @@ public: const char *getName() const override { return "profile-stats"; } bool shouldPrint(const BinaryFunction &) const override { return false; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// Prints a list of the top 100 functions sorted by a set of @@ -406,7 +406,7 @@ public: const char *getName() const override { return "print-stats"; } bool shouldPrint(const BinaryFunction &) const override { return false; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// Pass for lowering any instructions that we have raised and that have @@ -418,7 +418,7 @@ public: const char *getName() const override { return "inst-lowering"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// Pass for stripping 'repz' from 'repz retq' sequence of instructions. @@ -429,7 +429,7 @@ public: const char *getName() const override { return "strip-rep-ret"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// Pass for inlining calls to memcpy using 'rep movsb' on X86. @@ -440,7 +440,7 @@ public: const char *getName() const override { return "inline-memcpy"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// Pass for specializing memcpy for a size of 1 byte. @@ -461,7 +461,7 @@ public: const char *getName() const override { return "specialize-memcpy"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; /// Pass to remove nops in code @@ -475,7 +475,7 @@ public: const char *getName() const override { return "remove-nops"; } /// Pass entry point - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; enum FrameOptimizationType : char { diff --git a/bolt/include/bolt/Passes/CMOVConversion.h b/bolt/include/bolt/Passes/CMOVConversion.h index 77ce2235001a6d51862a62c088c663ebf98eeca4..4046266fa39d2413fa2429051c2b7362610d7bfd 100644 --- a/bolt/include/bolt/Passes/CMOVConversion.h +++ b/bolt/include/bolt/Passes/CMOVConversion.h @@ -64,7 +64,7 @@ class CMOVConversion : public BinaryFunctionPass { } double getMPRatio() { return (double)RemovedMP / PossibleMP; } - void dump(); + void dumpTo(raw_ostream &OS); }; // BinaryContext-wide stats Stats Global; @@ -76,7 +76,7 @@ public: const char *getName() const override { return "CMOV conversion"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/CacheMetrics.h b/bolt/include/bolt/Passes/CacheMetrics.h index 1e40ad66d933d64d7a38e45821ce122b58f3658f..5c88d98c76c1d5aa20b386a5398e3ee010867243 100644 --- a/bolt/include/bolt/Passes/CacheMetrics.h +++ b/bolt/include/bolt/Passes/CacheMetrics.h @@ -17,12 +17,16 @@ #include namespace llvm { + +class raw_ostream; + namespace bolt { class BinaryFunction; namespace CacheMetrics { /// Calculate and print various metrics related to instruction cache performance -void printAll(const std::vector &BinaryFunctions); +void printAll(raw_ostream &OS, + const std::vector &BinaryFunctions); } // namespace CacheMetrics } // namespace bolt diff --git a/bolt/include/bolt/Passes/FixRISCVCallsPass.h b/bolt/include/bolt/Passes/FixRISCVCallsPass.h index 46418c43d1928f4a6e65f2be371f3127246654c0..a5c3e5158d6d942cdc16f7c23c777a7269618e2a 100644 --- a/bolt/include/bolt/Passes/FixRISCVCallsPass.h +++ b/bolt/include/bolt/Passes/FixRISCVCallsPass.h @@ -33,7 +33,7 @@ public: const char *getName() const override { return "fix-riscv-calls"; } /// Pass entry point - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/FixRelaxationPass.h b/bolt/include/bolt/Passes/FixRelaxationPass.h index 45ee9cb736037c0c405115ed10cb583f065b09a6..50b64480aa62e53a2faaf1f0f8a7114d43b5bf91 100644 --- a/bolt/include/bolt/Passes/FixRelaxationPass.h +++ b/bolt/include/bolt/Passes/FixRelaxationPass.h @@ -31,7 +31,7 @@ public: const char *getName() const override { return "fix-relaxations"; } /// Pass entry point - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/FrameOptimizer.h b/bolt/include/bolt/Passes/FrameOptimizer.h index 310bebfee266ab81f13237133687823fba026474..64055bd251729bdc6daa616a9496e1ccec4f96ba 100644 --- a/bolt/include/bolt/Passes/FrameOptimizer.h +++ b/bolt/include/bolt/Passes/FrameOptimizer.h @@ -98,8 +98,8 @@ class FrameOptimizerPass : public BinaryFunctionPass { void removeUnusedStores(const FrameAnalysis &FA, BinaryFunction &BF); /// Perform shrinkwrapping step - void performShrinkWrapping(const RegAnalysis &RA, const FrameAnalysis &FA, - BinaryContext &BC); + Error performShrinkWrapping(const RegAnalysis &RA, const FrameAnalysis &FA, + BinaryContext &BC); public: explicit FrameOptimizerPass(const cl::opt &PrintPass) @@ -108,7 +108,7 @@ public: const char *getName() const override { return "frame-optimizer"; } /// Pass entry point - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; bool shouldPrint(const BinaryFunction &BF) const override { return BinaryFunctionPass::shouldPrint(BF) && FuncsChanged.count(&BF) > 0; diff --git a/bolt/include/bolt/Passes/Hugify.h b/bolt/include/bolt/Passes/Hugify.h index 0a7734059121c110ee633fb81056d03a174c8922..52c0ae19102b67520e05ecea110f8fcc3cd835b5 100644 --- a/bolt/include/bolt/Passes/Hugify.h +++ b/bolt/include/bolt/Passes/Hugify.h @@ -18,7 +18,7 @@ class HugePage : public BinaryFunctionPass { public: HugePage(const cl::opt &PrintPass) : BinaryFunctionPass(PrintPass) {} - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; const char *getName() const override { return "HugePage"; } }; diff --git a/bolt/include/bolt/Passes/IdenticalCodeFolding.h b/bolt/include/bolt/Passes/IdenticalCodeFolding.h index c15cebc8af19a4253d3c55ead67d670e5a98bddd..b4206fa360744586cb0a90284f14e47c19915bc0 100644 --- a/bolt/include/bolt/Passes/IdenticalCodeFolding.h +++ b/bolt/include/bolt/Passes/IdenticalCodeFolding.h @@ -35,7 +35,7 @@ public: : BinaryFunctionPass(PrintPass) {} const char *getName() const override { return "identical-code-folding"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/IndirectCallPromotion.h b/bolt/include/bolt/Passes/IndirectCallPromotion.h index 397a38663948e9cbb2d7d2ed72947ade0f373e64..adc58d70ec0f4d9e5bb09765d1ce863c0bdf15df 100644 --- a/bolt/include/bolt/Passes/IndirectCallPromotion.h +++ b/bolt/include/bolt/Passes/IndirectCallPromotion.h @@ -221,7 +221,7 @@ public: return BF.isSimple() && !BF.isIgnored() && BF.hasProfile() && !BF.hasUnknownControlFlow(); } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/Inliner.h b/bolt/include/bolt/Passes/Inliner.h index 711eae69d1c9fc81a436551af4085eeeb2629a51..5d9b96a2d915c133bb295c00632a59cb98b76067 100644 --- a/bolt/include/bolt/Passes/Inliner.h +++ b/bolt/include/bolt/Passes/Inliner.h @@ -86,7 +86,7 @@ public: return BinaryFunctionPass::shouldPrint(BF) && Modified.count(&BF) > 0; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/Instrumentation.h b/bolt/include/bolt/Passes/Instrumentation.h index 1a11f9eab511096e903616565d3c7bfe9c5ff305..76ffcf41db6ea9b6e2543a32191b4e9204776429 100644 --- a/bolt/include/bolt/Passes/Instrumentation.h +++ b/bolt/include/bolt/Passes/Instrumentation.h @@ -31,7 +31,7 @@ public: Summary(std::make_unique()) {} /// Modifies all functions by inserting instrumentation code (first step) - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; const char *getName() const override { return "instrumentation"; } diff --git a/bolt/include/bolt/Passes/JTFootprintReduction.h b/bolt/include/bolt/Passes/JTFootprintReduction.h index 084049d3b4631d376c4c093cabc872bf2d84b254..4b015e1f96b315abe0116c5de80e29b336045d85 100644 --- a/bolt/include/bolt/Passes/JTFootprintReduction.h +++ b/bolt/include/bolt/Passes/JTFootprintReduction.h @@ -68,7 +68,7 @@ public: bool shouldPrint(const BinaryFunction &BF) const override { return BinaryFunctionPass::shouldPrint(BF) && Modified.count(&BF) > 0; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/LongJmp.h b/bolt/include/bolt/Passes/LongJmp.h index c95181922dbc735c351cf5c4c29db411b9372145..3d02d75ac4a277eab0207157e8c0fca341ddba00 100644 --- a/bolt/include/bolt/Passes/LongJmp.h +++ b/bolt/include/bolt/Passes/LongJmp.h @@ -131,14 +131,14 @@ class LongJmpPass : public BinaryFunctionPass { uint64_t DotAddress) const; /// Expand the range of the stub in StubBB if necessary - bool relaxStub(BinaryBasicBlock &StubBB); + Error relaxStub(BinaryBasicBlock &StubBB, bool &Modified); /// Helper to resolve a symbol address according to our tentative layout uint64_t getSymbolAddress(const BinaryContext &BC, const MCSymbol *Target, const BinaryBasicBlock *TgtBB) const; /// Relax function by adding necessary stubs or relaxing existing stubs - bool relax(BinaryFunction &BF); + Error relax(BinaryFunction &BF, bool &Modified); public: /// BinaryPass public interface @@ -148,7 +148,7 @@ public: const char *getName() const override { return "long-jmp"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt } // namespace llvm diff --git a/bolt/include/bolt/Passes/LoopInversionPass.h b/bolt/include/bolt/Passes/LoopInversionPass.h index 472fb36640c14050110d1cc91d5d19cfef1e64fe..aee441d720931b6a799a04d25fa8831fdf2e925d 100644 --- a/bolt/include/bolt/Passes/LoopInversionPass.h +++ b/bolt/include/bolt/Passes/LoopInversionPass.h @@ -49,7 +49,7 @@ public: const char *getName() const override { return "loop-inversion-opt"; } /// Pass entry point - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; bool runOnFunction(BinaryFunction &Function); }; diff --git a/bolt/include/bolt/Passes/PLTCall.h b/bolt/include/bolt/Passes/PLTCall.h index 4fdbf60c7f9f857a34e84b4a2735261789cfda3b..09ef96e27293dac0b79b476bc74901b642ad9663 100644 --- a/bolt/include/bolt/Passes/PLTCall.h +++ b/bolt/include/bolt/Passes/PLTCall.h @@ -30,7 +30,7 @@ public: bool shouldPrint(const BinaryFunction &BF) const override { return BinaryFunctionPass::shouldPrint(BF); } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/PatchEntries.h b/bolt/include/bolt/Passes/PatchEntries.h index b9ed4a5e4280372b1c2112799b677af85f7562d1..fa6b5811a4c3b1956be22df2a59b6064ab6c8325 100644 --- a/bolt/include/bolt/Passes/PatchEntries.h +++ b/bolt/include/bolt/Passes/PatchEntries.h @@ -34,7 +34,7 @@ public: explicit PatchEntries() : BinaryFunctionPass(false) {} const char *getName() const override { return "patch-entries"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/RegReAssign.h b/bolt/include/bolt/Passes/RegReAssign.h index cd7bea6a62c15a5723088df83948d42b3edb1aa1..c50e32ff46e293490a8a341688482ead881d59a9 100644 --- a/bolt/include/bolt/Passes/RegReAssign.h +++ b/bolt/include/bolt/Passes/RegReAssign.h @@ -55,7 +55,7 @@ public: return BinaryFunctionPass::shouldPrint(BF) && FuncsChanged.count(&BF) > 0; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt } // namespace llvm diff --git a/bolt/include/bolt/Passes/ReorderData.h b/bolt/include/bolt/Passes/ReorderData.h index 65b7306521019b06dd563e50ab3037c95a7d3e11..9cd17aecfd81944eb6711ac5a3176f919d9fb1ab 100644 --- a/bolt/include/bolt/Passes/ReorderData.h +++ b/bolt/include/bolt/Passes/ReorderData.h @@ -35,7 +35,8 @@ private: sortedByFunc(BinaryContext &BC, const BinarySection &Section, std::map &BFs) const; - void printOrder(const BinarySection &Section, DataOrder::const_iterator Begin, + void printOrder(BinaryContext &BC, const BinarySection &Section, + DataOrder::const_iterator Begin, DataOrder::const_iterator End) const; /// Set the ordering of the section with \p SectionName. \p NewOrder is a @@ -51,7 +52,7 @@ public: const char *getName() const override { return "reorder-data"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/ReorderFunctions.h b/bolt/include/bolt/Passes/ReorderFunctions.h index 8f9507d0a82494351fe68b765535d08c76e471c5..4c88142c588714382554810c910044ce6e09b323 100644 --- a/bolt/include/bolt/Passes/ReorderFunctions.h +++ b/bolt/include/bolt/Passes/ReorderFunctions.h @@ -20,10 +20,10 @@ class Cluster; class ReorderFunctions : public BinaryFunctionPass { BinaryFunctionCallGraph Cg; - void reorder(std::vector &&Clusters, + void reorder(BinaryContext &BC, std::vector &&Clusters, std::map &BFs); - void printStats(const std::vector &Clusters, + void printStats(BinaryContext &BC, const std::vector &Clusters, const std::vector &FuncAddr); public: @@ -42,9 +42,9 @@ public: : BinaryFunctionPass(PrintPass) {} const char *getName() const override { return "reorder-functions"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; - static std::vector readFunctionOrderFile(); + static Error readFunctionOrderFile(std::vector &FunctionNames); }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/RetpolineInsertion.h b/bolt/include/bolt/Passes/RetpolineInsertion.h index 12f46a95264c93d6ccfa898e0c2c5335b3b7c63a..2cdde7f0748345f11057ca72759ee0155c1d5f2f 100644 --- a/bolt/include/bolt/Passes/RetpolineInsertion.h +++ b/bolt/include/bolt/Passes/RetpolineInsertion.h @@ -62,7 +62,7 @@ public: const char *getName() const override { return "retpoline-insertion"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/ShrinkWrapping.h b/bolt/include/bolt/Passes/ShrinkWrapping.h index cccbc518dd26b5c4adfea71af25e00a235f5a5d2..b7809f0bb0698497d2a86ff040ab6108abb7c10c 100644 --- a/bolt/include/bolt/Passes/ShrinkWrapping.h +++ b/bolt/include/bolt/Passes/ShrinkWrapping.h @@ -467,8 +467,9 @@ private: /// If \p CreatePushOrPop is true, create a push/pop instead. Current SP/FP /// values, as determined by StackPointerTracking, should be informed via /// \p SPVal and \p FPVal in order to emit the correct offset form SP/FP. - MCInst createStackAccess(int SPVal, int FPVal, const FrameIndexEntry &FIE, - bool CreatePushOrPop); + Expected createStackAccess(int SPVal, int FPVal, + const FrameIndexEntry &FIE, + bool CreatePushOrPop); /// Update the CFI referenced by \p Inst with \p NewOffset, if the CFI has /// an offset. @@ -484,22 +485,23 @@ private: /// InsertionPoint for other instructions that need to be inserted at the same /// original location, since this insertion may have invalidated the previous /// location. - BBIterTy processInsertion(BBIterTy InsertionPoint, BinaryBasicBlock *CurBB, - const WorklistItem &Item, int64_t SPVal, - int64_t FPVal); + Expected processInsertion(BBIterTy InsertionPoint, + BinaryBasicBlock *CurBB, + const WorklistItem &Item, int64_t SPVal, + int64_t FPVal); /// Auxiliary function to processInsertions(), helping perform all the /// insertion tasks in the todo list associated with a single insertion point. /// Return true if at least one insertion was performed. - BBIterTy processInsertionsList(BBIterTy InsertionPoint, - BinaryBasicBlock *CurBB, - std::vector &TodoList, - int64_t SPVal, int64_t FPVal); + Expected processInsertionsList(BBIterTy InsertionPoint, + BinaryBasicBlock *CurBB, + std::vector &TodoList, + int64_t SPVal, int64_t FPVal); /// Apply all insertion todo tasks regarding insertion of new stores/loads or /// push/pops at annotated points. Return false if the entire function had /// no todo tasks annotation and this pass has nothing to do. - bool processInsertions(); + Expected processInsertions(); /// Apply all deletion todo tasks (or tasks to change a push/pop to a memory /// access no-op) @@ -519,9 +521,9 @@ public: BC.MIB->removeAnnotation(Inst, getAnnotationIndex()); } - bool perform(bool HotOnly = false); + Expected perform(bool HotOnly = false); - static void printStats(); + static void printStats(BinaryContext &BC); }; } // end namespace bolt diff --git a/bolt/include/bolt/Passes/SplitFunctions.h b/bolt/include/bolt/Passes/SplitFunctions.h index 28e9e79d1b8f87c9442163d12903315a84a6e892..8bdc48b68eb7ae94c3ec36b167c6e349bb6e6f31 100644 --- a/bolt/include/bolt/Passes/SplitFunctions.h +++ b/bolt/include/bolt/Passes/SplitFunctions.h @@ -104,7 +104,7 @@ public: const char *getName() const override { return "split-functions"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/StokeInfo.h b/bolt/include/bolt/Passes/StokeInfo.h index 75cfa1e7de4355d827e746f440a3e94ebcba4879..76417e6a2c3baa612ff7041142d8bba4933b3f04 100644 --- a/bolt/include/bolt/Passes/StokeInfo.h +++ b/bolt/include/bolt/Passes/StokeInfo.h @@ -120,7 +120,7 @@ public: bool checkFunction(BinaryFunction &BF, DataflowInfoManager &DInfo, RegAnalysis &RA, StokeFuncInfo &FuncInfo); - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/TailDuplication.h b/bolt/include/bolt/Passes/TailDuplication.h index b3f1d7b7d9643a4afc93bc03e54cfbe6c78953de..a2fcab0720ca27ac69c5ba44f6c1e1975193bb97 100644 --- a/bolt/include/bolt/Passes/TailDuplication.h +++ b/bolt/include/bolt/Passes/TailDuplication.h @@ -145,7 +145,7 @@ public: const char *getName() const override { return "tail duplication"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/ThreeWayBranch.h b/bolt/include/bolt/Passes/ThreeWayBranch.h index 3eabf1b27e9d4edee87e4ee0fc6efb3da67a8256..9abf4c34134fddfdfafe9deb0afddc8179d3ac35 100644 --- a/bolt/include/bolt/Passes/ThreeWayBranch.h +++ b/bolt/include/bolt/Passes/ThreeWayBranch.h @@ -32,7 +32,7 @@ public: const char *getName() const override { return "three way branch"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Passes/ValidateInternalCalls.h b/bolt/include/bolt/Passes/ValidateInternalCalls.h index 137b83b0179f49948d42a52223e1d533690148bd..0cdb8584f92df26a96bc0f7c994cc556b2887043 100644 --- a/bolt/include/bolt/Passes/ValidateInternalCalls.h +++ b/bolt/include/bolt/Passes/ValidateInternalCalls.h @@ -54,7 +54,7 @@ public: const char *getName() const override { return "validate-internal-calls"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; private: /// Fix the CFG to take into consideration internal calls that do not diff --git a/bolt/include/bolt/Passes/ValidateMemRefs.h b/bolt/include/bolt/Passes/ValidateMemRefs.h index d33862cf7b1697f38818069fe3212178522a7aff..90acce370249afefdd7507f716cfb849b64618f4 100644 --- a/bolt/include/bolt/Passes/ValidateMemRefs.h +++ b/bolt/include/bolt/Passes/ValidateMemRefs.h @@ -25,7 +25,7 @@ public: const char *getName() const override { return "validate-mem-refs"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; private: bool checkAndFixJTReference(BinaryFunction &BF, MCInst &Inst, diff --git a/bolt/include/bolt/Passes/VeneerElimination.h b/bolt/include/bolt/Passes/VeneerElimination.h index 10c849674ab6dfd79b55118a6d98dd683e4e4c70..9ba10408a4c87be31e5e438708bd10a40c2666ad 100644 --- a/bolt/include/bolt/Passes/VeneerElimination.h +++ b/bolt/include/bolt/Passes/VeneerElimination.h @@ -22,7 +22,7 @@ public: const char *getName() const override { return "veneer-elimination"; } - void runOnFunctions(BinaryContext &BC) override; + Error runOnFunctions(BinaryContext &BC) override; }; } // namespace bolt diff --git a/bolt/include/bolt/Profile/BoltAddressTranslation.h b/bolt/include/bolt/Profile/BoltAddressTranslation.h index fa29ece3287a9a489fa7086175a27336674fa955..b9d1e865646b44acc5eb1ed76ec2dd6aa0854f5a 100644 --- a/bolt/include/bolt/Profile/BoltAddressTranslation.h +++ b/bolt/include/bolt/Profile/BoltAddressTranslation.h @@ -85,7 +85,7 @@ public: /// Read the serialized address translation tables and load them internally /// in memory. Return a parse error if failed. - std::error_code parse(StringRef Buf); + std::error_code parse(raw_ostream &OS, StringRef Buf); /// Dump the parsed address translation tables void dump(raw_ostream &OS); diff --git a/bolt/include/bolt/Rewrite/BinaryPassManager.h b/bolt/include/bolt/Rewrite/BinaryPassManager.h index 84ab192c415a403d201becde0832bf3c4017404d..2297c3bf52fd665fde96b90bc93af21a60702d6c 100644 --- a/bolt/include/bolt/Rewrite/BinaryPassManager.h +++ b/bolt/include/bolt/Rewrite/BinaryPassManager.h @@ -46,10 +46,10 @@ public: } /// Run all registered passes in the order they were added. - void runPasses(); + Error runPasses(); /// Runs all enabled implemented passes on all functions. - static void runAllPasses(BinaryContext &BC); + static Error runAllPasses(BinaryContext &BC); }; } // namespace bolt diff --git a/bolt/include/bolt/Rewrite/RewriteInstance.h b/bolt/include/bolt/Rewrite/RewriteInstance.h index 170da78846b8f30a2725b2eec03af21a6e9d661d..97ab65cd5a4a1ffd26df3e575b8ce2853437405d 100644 --- a/bolt/include/bolt/Rewrite/RewriteInstance.h +++ b/bolt/include/bolt/Rewrite/RewriteInstance.h @@ -47,11 +47,14 @@ public: // construction. Constructors can’t return errors, so clients must test \p Err // after the object is constructed. Use `create` method instead. RewriteInstance(llvm::object::ELFObjectFileBase *File, const int Argc, - const char *const *Argv, StringRef ToolPath, Error &Err); + const char *const *Argv, StringRef ToolPath, + raw_ostream &Stdout, raw_ostream &Stderr, Error &Err); static Expected> create(llvm::object::ELFObjectFileBase *File, const int Argc, - const char *const *Argv, StringRef ToolPath); + const char *const *Argv, StringRef ToolPath, + raw_ostream &Stdout = llvm::outs(), + raw_ostream &Stderr = llvm::errs()); ~RewriteInstance(); /// Assign profile from \p Filename to this instance. diff --git a/bolt/lib/Core/BinaryBasicBlock.cpp b/bolt/lib/Core/BinaryBasicBlock.cpp index 984bc6dbd220ab05904e3ee909e46f56983c2304..4a83fece0e43d4eba92e95afd17c5988092be72a 100644 --- a/bolt/lib/Core/BinaryBasicBlock.cpp +++ b/bolt/lib/Core/BinaryBasicBlock.cpp @@ -92,8 +92,8 @@ bool BinaryBasicBlock::validateSuccessorInvariants() { // Work on the assumption that jump table blocks don't // have a conditional successor. Valid = false; - errs() << "BOLT-WARNING: Jump table successor " << Succ->getName() - << " not contained in the jump table.\n"; + BC.errs() << "BOLT-WARNING: Jump table successor " << Succ->getName() + << " not contained in the jump table.\n"; } } // If there are any leftover entries in the jump table, they @@ -103,8 +103,8 @@ bool BinaryBasicBlock::validateSuccessorInvariants() { Valid &= (Sym == Function->getFunctionEndLabel() || Sym == Function->getFunctionEndLabel(getFragmentNum())); if (!Valid) { - errs() << "BOLT-WARNING: Jump table contains illegal entry: " - << Sym->getName() << "\n"; + BC.errs() << "BOLT-WARNING: Jump table contains illegal entry: " + << Sym->getName() << "\n"; } } } @@ -141,11 +141,11 @@ bool BinaryBasicBlock::validateSuccessorInvariants() { } } if (!Valid) { - errs() << "BOLT-WARNING: CFG invalid in " << *getFunction() << " @ " - << getName() << "\n"; + BC.errs() << "BOLT-WARNING: CFG invalid in " << *getFunction() << " @ " + << getName() << "\n"; if (JT) { - errs() << "Jump Table instruction addr = 0x" - << Twine::utohexstr(BC.MIB->getJumpTable(*Inst)) << "\n"; + BC.errs() << "Jump Table instruction addr = 0x" + << Twine::utohexstr(BC.MIB->getJumpTable(*Inst)) << "\n"; JT->print(errs()); } getFunction()->dump(); @@ -520,9 +520,9 @@ uint32_t BinaryBasicBlock::getNumPseudos() const { ++N; if (N != NumPseudos) { - errs() << "BOLT-ERROR: instructions for basic block " << getName() - << " in function " << *Function << ": calculated pseudos " << N - << ", set pseudos " << NumPseudos << ", size " << size() << '\n'; + BC.errs() << "BOLT-ERROR: instructions for basic block " << getName() + << " in function " << *Function << ": calculated pseudos " << N + << ", set pseudos " << NumPseudos << ", size " << size() << '\n'; llvm_unreachable("pseudos mismatch"); } #endif @@ -559,18 +559,18 @@ BinaryBasicBlock::getBranchStats(const BinaryBasicBlock *Succ) const { void BinaryBasicBlock::dump() const { BinaryContext &BC = Function->getBinaryContext(); if (Label) - outs() << Label->getName() << ":\n"; - BC.printInstructions(outs(), Instructions.begin(), Instructions.end(), + BC.outs() << Label->getName() << ":\n"; + BC.printInstructions(BC.outs(), Instructions.begin(), Instructions.end(), getOffset(), Function); - outs() << "preds:"; + BC.outs() << "preds:"; for (auto itr = pred_begin(); itr != pred_end(); ++itr) { - outs() << " " << (*itr)->getName(); + BC.outs() << " " << (*itr)->getName(); } - outs() << "\nsuccs:"; + BC.outs() << "\nsuccs:"; for (auto itr = succ_begin(); itr != succ_end(); ++itr) { - outs() << " " << (*itr)->getName(); + BC.outs() << " " << (*itr)->getName(); } - outs() << "\n"; + BC.outs() << "\n"; } uint64_t BinaryBasicBlock::estimateSize(const MCCodeEmitter *Emitter) const { diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index df835d2876804a1b3b2242e3a96efd8226a6d7af..d544ece13a832fd5e7f898108269b163c993fe2b 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -83,6 +83,46 @@ cl::opt CompDirOverride( namespace llvm { namespace bolt { +char BOLTError::ID = 0; + +BOLTError::BOLTError(bool IsFatal, const Twine &S) + : IsFatal(IsFatal), Msg(S.str()) {} + +void BOLTError::log(raw_ostream &OS) const { + if (IsFatal) + OS << "FATAL "; + StringRef ErrMsg = StringRef(Msg); + // Prepend our error prefix if it is missing + if (ErrMsg.empty()) { + OS << "BOLT-ERROR\n"; + } else { + if (!ErrMsg.starts_with("BOLT-ERROR")) + OS << "BOLT-ERROR: "; + OS << ErrMsg << "\n"; + } +} + +std::error_code BOLTError::convertToErrorCode() const { + return inconvertibleErrorCode(); +} + +Error createNonFatalBOLTError(const Twine &S) { + return make_error(/*IsFatal*/ false, S); +} + +Error createFatalBOLTError(const Twine &S) { + return make_error(/*IsFatal*/ true, S); +} + +void BinaryContext::logBOLTErrorsAndQuitOnFatal(Error E) { + handleAllErrors(Error(std::move(E)), [&](const BOLTError &E) { + if (!E.getMessage().empty()) + E.log(this->errs()); + if (E.isFatal()) + exit(1); + }); +} + BinaryContext::BinaryContext(std::unique_ptr Ctx, std::unique_ptr DwCtx, std::unique_ptr TheTriple, @@ -96,13 +136,15 @@ BinaryContext::BinaryContext(std::unique_ptr Ctx, std::unique_ptr MIA, std::unique_ptr MIB, std::unique_ptr MRI, - std::unique_ptr DisAsm) + std::unique_ptr DisAsm, + JournalingStreams Logger) : Ctx(std::move(Ctx)), DwCtx(std::move(DwCtx)), TheTriple(std::move(TheTriple)), TheTarget(TheTarget), TripleName(TripleName), MCE(std::move(MCE)), MOFI(std::move(MOFI)), AsmInfo(std::move(AsmInfo)), MII(std::move(MII)), STI(std::move(STI)), InstPrinter(std::move(InstPrinter)), MIA(std::move(MIA)), - MIB(std::move(MIB)), MRI(std::move(MRI)), DisAsm(std::move(DisAsm)) { + MIB(std::move(MIB)), MRI(std::move(MRI)), DisAsm(std::move(DisAsm)), + Logger(Logger) { Relocation::Arch = this->TheTriple->getArch(); RegularPageSize = isAArch64() ? RegularPageSizeAArch64 : RegularPageSizeX86; PageAlign = opts::NoHugePages ? RegularPageSize : HugePageSize; @@ -122,7 +164,8 @@ BinaryContext::~BinaryContext() { /// triple \p TripleName. Expected> BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC, - std::unique_ptr DwCtx) { + std::unique_ptr DwCtx, + JournalingStreams Logger) { StringRef ArchName = ""; std::string FeaturesStr = ""; switch (File->getArch()) { @@ -241,17 +284,12 @@ BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC, std::unique_ptr MCE( TheTarget->createMCCodeEmitter(*MII, *Ctx)); - // Make sure we don't miss any output on core dumps. - outs().SetUnbuffered(); - errs().SetUnbuffered(); - dbgs().SetUnbuffered(); - auto BC = std::make_unique( std::move(Ctx), std::move(DwCtx), std::move(TheTriple), TheTarget, std::string(TripleName), std::move(MCE), std::move(MOFI), std::move(AsmInfo), std::move(MII), std::move(STI), std::move(InstructionPrinter), std::move(MIA), nullptr, std::move(MRI), - std::move(DisAsm)); + std::move(DisAsm), Logger); BC->LSDAEncoding = LSDAEncoding; @@ -304,9 +342,9 @@ bool BinaryContext::validateObjectNesting() const { Itr->second->containsRange(Next->second->getAddress(), Next->second->getSize())) { if (Next->second->Parent != Itr->second) { - errs() << "BOLT-WARNING: object nesting incorrect for:\n" - << "BOLT-WARNING: " << *Itr->second << "\n" - << "BOLT-WARNING: " << *Next->second << "\n"; + this->errs() << "BOLT-WARNING: object nesting incorrect for:\n" + << "BOLT-WARNING: " << *Itr->second << "\n" + << "BOLT-WARNING: " << *Next->second << "\n"; Valid = false; } ++Next; @@ -323,14 +361,16 @@ bool BinaryContext::validateHoles() const { uint64_t RelAddr = Rel.Offset + Section.getAddress(); const BinaryData *BD = getBinaryDataContainingAddress(RelAddr); if (!BD) { - errs() << "BOLT-WARNING: no BinaryData found for relocation at address" - << " 0x" << Twine::utohexstr(RelAddr) << " in " - << Section.getName() << "\n"; + this->errs() + << "BOLT-WARNING: no BinaryData found for relocation at address" + << " 0x" << Twine::utohexstr(RelAddr) << " in " << Section.getName() + << "\n"; Valid = false; } else if (!BD->getAtomicRoot()) { - errs() << "BOLT-WARNING: no atomic BinaryData found for relocation at " - << "address 0x" << Twine::utohexstr(RelAddr) << " in " - << Section.getName() << "\n"; + this->errs() + << "BOLT-WARNING: no atomic BinaryData found for relocation at " + << "address 0x" << Twine::utohexstr(RelAddr) << " in " + << Section.getName() << "\n"; Valid = false; } } @@ -438,8 +478,9 @@ BinaryContext::handleAddressRef(uint64_t Address, BinaryFunction &BF, // The address could potentially escape. Mark it as another entry // point into the function. if (opts::Verbosity >= 1) { - outs() << "BOLT-INFO: potentially escaped address 0x" - << Twine::utohexstr(Address) << " in function " << BF << '\n'; + this->outs() << "BOLT-INFO: potentially escaped address 0x" + << Twine::utohexstr(Address) << " in function " << BF + << '\n'; } BF.HasInternalLabelReference = true; return std::make_pair( @@ -482,9 +523,9 @@ MemoryContentsType BinaryContext::analyzeMemoryAt(uint64_t Address, // internal function addresses to escape the function scope - we // consider it a tail call. if (opts::Verbosity > 1) { - errs() << "BOLT-WARNING: no section for address 0x" - << Twine::utohexstr(Address) << " referenced from function " << BF - << '\n'; + this->errs() << "BOLT-WARNING: no section for address 0x" + << Twine::utohexstr(Address) << " referenced from function " + << BF << '\n'; } return MemoryContentsType::UNKNOWN; } @@ -730,7 +771,7 @@ void BinaryContext::skipMarkedFragments() { assert(FragmentsToSkip.count(BF) && "internal error in traversing function fragments"); if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: Ignoring " << BF->getPrintName() << '\n'; + this->errs() << "BOLT-WARNING: Ignoring " << BF->getPrintName() << '\n'; BF->setSimple(false); BF->setHasIndirectTargetToSplitFragment(true); @@ -738,9 +779,9 @@ void BinaryContext::skipMarkedFragments() { llvm::for_each(BF->ParentFragments, addToWorklist); } if (!FragmentsToSkip.empty()) - errs() << "BOLT-WARNING: skipped " << FragmentsToSkip.size() << " function" - << (FragmentsToSkip.size() == 1 ? "" : "s") - << " due to cold fragments\n"; + this->errs() << "BOLT-WARNING: skipped " << FragmentsToSkip.size() + << " function" << (FragmentsToSkip.size() == 1 ? "" : "s") + << " due to cold fragments\n"; } MCSymbol *BinaryContext::getOrCreateGlobalSymbol(uint64_t Address, Twine Prefix, @@ -791,10 +832,10 @@ BinaryContext::getOrCreateJumpTable(BinaryFunction &Function, uint64_t Address, // Duplicate the entry for the parent function for easy access JT->Parents.push_back(&Function); if (opts::Verbosity > 2) { - outs() << "BOLT-INFO: Multiple fragments access same jump table: " - << JT->Parents[0]->getPrintName() << "; " - << Function.getPrintName() << "\n"; - JT->print(outs()); + this->outs() << "BOLT-INFO: Multiple fragments access same jump table: " + << JT->Parents[0]->getPrintName() << "; " + << Function.getPrintName() << "\n"; + JT->print(this->outs()); } Function.JumpTables.emplace(Address, JT); JT->Parents[0]->setHasIndirectTargetToSplitFragment(true); @@ -832,7 +873,7 @@ BinaryContext::getOrCreateJumpTable(BinaryFunction &Function, uint64_t Address, *getSectionForAddress(Address)); JT->Parents.push_back(&Function); if (opts::Verbosity > 2) - JT->print(outs()); + JT->print(this->outs()); JumpTables.emplace(Address, JT); // Duplicate the entry for the parent function for easy access. @@ -961,12 +1002,13 @@ bool BinaryContext::hasValidCodePadding(const BinaryFunction &BF) { return true; if (opts::Verbosity >= 1) { - errs() << "BOLT-WARNING: bad padding at address 0x" - << Twine::utohexstr(BF.getAddress() + BF.getSize()) - << " starting at offset " << (Offset - BF.getSize()) - << " in function " << BF << '\n' - << FunctionData->slice(BF.getSize(), BF.getMaxSize() - BF.getSize()) - << '\n'; + this->errs() << "BOLT-WARNING: bad padding at address 0x" + << Twine::utohexstr(BF.getAddress() + BF.getSize()) + << " starting at offset " << (Offset - BF.getSize()) + << " in function " << BF << '\n' + << FunctionData->slice(BF.getSize(), + BF.getMaxSize() - BF.getSize()) + << '\n'; } return false; @@ -981,8 +1023,8 @@ void BinaryContext::adjustCodePadding() { if (!hasValidCodePadding(BF)) { if (HasRelocations) { if (opts::Verbosity >= 1) { - outs() << "BOLT-INFO: function " << BF - << " has invalid padding. Ignoring the function.\n"; + this->outs() << "BOLT-INFO: function " << BF + << " has invalid padding. Ignoring the function.\n"; } BF.setIgnored(); } else { @@ -1130,8 +1172,8 @@ void BinaryContext::generateSymbolHashes() { // (i.e. all zeros or a "hole") if (!isPadding(BD)) { if (opts::Verbosity) { - errs() << "BOLT-WARNING: collision detected when hashing " << BD - << " with new name (" << NewName << "), skipping.\n"; + this->errs() << "BOLT-WARNING: collision detected when hashing " << BD + << " with new name (" << NewName << "), skipping.\n"; } ++NumCollisions; } @@ -1141,11 +1183,11 @@ void BinaryContext::generateSymbolHashes() { GlobalSymbols[NewName] = &BD; } if (NumCollisions) { - errs() << "BOLT-WARNING: " << NumCollisions - << " collisions detected while hashing binary objects"; + this->errs() << "BOLT-WARNING: " << NumCollisions + << " collisions detected while hashing binary objects"; if (!opts::Verbosity) - errs() << ". Use -v=1 to see the list."; - errs() << '\n'; + this->errs() << ". Use -v=1 to see the list."; + this->errs() << '\n'; } } @@ -1161,8 +1203,8 @@ bool BinaryContext::registerFragment(BinaryFunction &TargetFunction, Function.setSimple(false); } if (opts::Verbosity >= 1) { - outs() << "BOLT-INFO: marking " << TargetFunction << " as a fragment of " - << Function << '\n'; + this->outs() << "BOLT-INFO: marking " << TargetFunction + << " as a fragment of " << Function << '\n'; } return true; } @@ -1276,10 +1318,11 @@ void BinaryContext::processInterproceduralReferences() { if (TargetFunction) { if (TargetFunction->isFragment() && !TargetFunction->isChildOf(Function)) { - errs() << "BOLT-WARNING: interprocedural reference between unrelated " - "fragments: " - << Function.getPrintName() << " and " - << TargetFunction->getPrintName() << '\n'; + this->errs() + << "BOLT-WARNING: interprocedural reference between unrelated " + "fragments: " + << Function.getPrintName() << " and " + << TargetFunction->getPrintName() << '\n'; } if (uint64_t Offset = Address - TargetFunction->getAddress()) TargetFunction->addEntryPointAtOffset(Offset); @@ -1305,9 +1348,10 @@ void BinaryContext::processInterproceduralReferences() { continue; if (opts::processAllFunctions()) { - errs() << "BOLT-ERROR: cannot process binaries with unmarked " - << "object in code at address 0x" << Twine::utohexstr(Address) - << " belonging to section " << SectionName << " in current mode\n"; + this->errs() << "BOLT-ERROR: cannot process binaries with unmarked " + << "object in code at address 0x" + << Twine::utohexstr(Address) << " belonging to section " + << SectionName << " in current mode\n"; exit(1); } @@ -1317,9 +1361,10 @@ void BinaryContext::processInterproceduralReferences() { // We are not going to overwrite non-simple functions, but for simple // ones - adjust the padding size. if (TargetFunction && TargetFunction->isSimple()) { - errs() << "BOLT-WARNING: function " << *TargetFunction - << " has an object detected in a padding region at address 0x" - << Twine::utohexstr(Address) << '\n'; + this->errs() + << "BOLT-WARNING: function " << *TargetFunction + << " has an object detected in a padding region at address 0x" + << Twine::utohexstr(Address) << '\n'; TargetFunction->setMaxSize(TargetFunction->getSize()); } } @@ -1336,7 +1381,8 @@ void BinaryContext::postProcessSymbolTable() { BD->getName().starts_with("DATAat")) && !BD->getParent() && !BD->getSize() && !BD->isAbsolute() && BD->getSection()) { - errs() << "BOLT-WARNING: zero-sized top level symbol: " << *BD << "\n"; + this->errs() << "BOLT-WARNING: zero-sized top level symbol: " << *BD + << "\n"; Valid = false; } } @@ -1592,17 +1638,18 @@ void BinaryContext::preprocessDWODebugInfo() { DWARFUnit *DWOCU = DwarfUnit->getNonSkeletonUnitDIE(false, AbsolutePath).getDwarfUnit(); if (!DWOCU->isDWOUnit()) { - outs() << "BOLT-WARNING: Debug Fission: DWO debug information for " - << DWOName - << " was not retrieved and won't be updated. Please check " - "relative path.\n"; + this->outs() + << "BOLT-WARNING: Debug Fission: DWO debug information for " + << DWOName + << " was not retrieved and won't be updated. Please check " + "relative path.\n"; continue; } DWOCUs[*DWOId] = DWOCU; } } if (!DWOCUs.empty()) - outs() << "BOLT-INFO: processing split DWARF\n"; + this->outs() << "BOLT-INFO: processing split DWARF\n"; } void BinaryContext::preprocessDebugInfo() { @@ -1663,8 +1710,8 @@ void BinaryContext::preprocessDebugInfo() { } if (opts::Verbosity >= 1) { - outs() << "BOLT-INFO: " << ProcessedCUs.size() << " out of " - << DwCtx->getNumCompileUnits() << " CUs will be updated\n"; + this->outs() << "BOLT-INFO: " << ProcessedCUs.size() << " out of " + << DwCtx->getNumCompileUnits() << " CUs will be updated\n"; } preprocessDWODebugInfo(); @@ -2245,23 +2292,26 @@ BinaryFunction *BinaryContext::getFunctionForSymbol(const MCSymbol *Symbol, return BF; } -void BinaryContext::exitWithBugReport(StringRef Message, - const BinaryFunction &Function) const { - errs() << "=======================================\n"; - errs() << "BOLT is unable to proceed because it couldn't properly understand " - "this function.\n"; - errs() << "If you are running the most recent version of BOLT, you may " - "want to " - "report this and paste this dump.\nPlease check that there is no " - "sensitive contents being shared in this dump.\n"; - errs() << "\nOffending function: " << Function.getPrintName() << "\n\n"; - ScopedPrinter SP(errs()); +std::string +BinaryContext::generateBugReportMessage(StringRef Message, + const BinaryFunction &Function) const { + std::string Msg; + raw_string_ostream SS(Msg); + SS << "=======================================\n"; + SS << "BOLT is unable to proceed because it couldn't properly understand " + "this function.\n"; + SS << "If you are running the most recent version of BOLT, you may " + "want to " + "report this and paste this dump.\nPlease check that there is no " + "sensitive contents being shared in this dump.\n"; + SS << "\nOffending function: " << Function.getPrintName() << "\n\n"; + ScopedPrinter SP(SS); SP.printBinaryBlock("Function contents", *Function.getData()); - errs() << "\n"; - Function.dump(); - errs() << "ERROR: " << Message; - errs() << "\n=======================================\n"; - exit(1); + SS << "\n"; + const_cast(Function).print(SS, ""); + SS << "ERROR: " << Message; + SS << "\n=======================================\n"; + return Msg; } BinaryFunction * @@ -2399,9 +2449,9 @@ bool BinaryContext::validateInstructionEncoding( auto OutputSequence = ArrayRef((uint8_t *)Code.data(), Code.size()); if (InputSequence != OutputSequence) { if (opts::Verbosity > 1) { - errs() << "BOLT-WARNING: mismatched encoding detected\n" - << " input: " << InputSequence << '\n' - << " output: " << OutputSequence << '\n'; + this->errs() << "BOLT-WARNING: mismatched encoding detected\n" + << " input: " << InputSequence << '\n' + << " output: " << OutputSequence << '\n'; } return false; } diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp index 3bff3125a57a8600f13540c54be3b360937c3601..d4b668c1d7e7bdd7346d2a9bae650173e8eb858a 100644 --- a/bolt/lib/Core/BinaryEmitter.cpp +++ b/bolt/lib/Core/BinaryEmitter.cpp @@ -567,7 +567,8 @@ void BinaryEmitter::emitConstantIslands(BinaryFunction &BF, bool EmitColdPart, BF.getAddress() - BF.getOriginSection()->getAddress(), BF.getMaxSize()); if (opts::Verbosity && !OnBehalfOf) - outs() << "BOLT-INFO: emitting constant island for function " << BF << "\n"; + BC.outs() << "BOLT-INFO: emitting constant island for function " << BF + << "\n"; // We split the island into smaller blocks and output labels between them. auto IS = Islands.Offsets.begin(); @@ -766,7 +767,7 @@ void BinaryEmitter::emitJumpTables(const BinaryFunction &BF) { return; if (opts::PrintJumpTables) - outs() << "BOLT-INFO: jump tables for function " << BF << ":\n"; + BC.outs() << "BOLT-INFO: jump tables for function " << BF << ":\n"; for (auto &JTI : BF.jumpTables()) { JumpTable &JT = *JTI.second; @@ -774,7 +775,7 @@ void BinaryEmitter::emitJumpTables(const BinaryFunction &BF) { if (JT.Parents.size() > 1 && JT.Parents[0] != &BF) continue; if (opts::PrintJumpTables) - JT.print(outs()); + JT.print(BC.outs()); if (opts::JumpTables == JTS_BASIC && BC.HasRelocations) { JT.updateOriginal(); } else { diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp index 0ac47a53a446775e536ec6b502601169477b07a4..54f2f9d972a46173d632f370aa106d6d84e33365 100644 --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -880,9 +880,9 @@ BinaryFunction::processIndirectBranch(MCInst &Instruction, unsigned Size, // internal function addresses to escape the function scope - we // consider it a tail call. if (opts::Verbosity >= 1) { - errs() << "BOLT-WARNING: no section for address 0x" - << Twine::utohexstr(ArrayStart) << " referenced from function " - << *this << '\n'; + BC.errs() << "BOLT-WARNING: no section for address 0x" + << Twine::utohexstr(ArrayStart) << " referenced from function " + << *this << '\n'; } return IndirectBranchType::POSSIBLE_TAIL_CALL; } @@ -899,11 +899,11 @@ BinaryFunction::processIndirectBranch(MCInst &Instruction, unsigned Size, if (BC.getSectionForAddress(ArrayStart)->isWritable()) return IndirectBranchType::UNKNOWN; - outs() << "BOLT-INFO: fixed indirect branch detected in " << *this - << " at 0x" << Twine::utohexstr(getAddress() + Offset) - << " referencing data at 0x" << Twine::utohexstr(ArrayStart) - << " the destination value is 0x" << Twine::utohexstr(*Value) - << '\n'; + BC.outs() << "BOLT-INFO: fixed indirect branch detected in " << *this + << " at 0x" << Twine::utohexstr(getAddress() + Offset) + << " referencing data at 0x" << Twine::utohexstr(ArrayStart) + << " the destination value is 0x" << Twine::utohexstr(*Value) + << '\n'; TargetAddress = *Value; return BranchType; @@ -1021,28 +1021,29 @@ bool BinaryFunction::isZeroPaddingAt(uint64_t Offset) const { return true; } -void BinaryFunction::handlePCRelOperand(MCInst &Instruction, uint64_t Address, - uint64_t Size) { +Error BinaryFunction::handlePCRelOperand(MCInst &Instruction, uint64_t Address, + uint64_t Size) { auto &MIB = BC.MIB; uint64_t TargetAddress = 0; if (!MIB->evaluateMemOperandTarget(Instruction, TargetAddress, Address, Size)) { - errs() << "BOLT-ERROR: PC-relative operand can't be evaluated:\n"; - BC.InstPrinter->printInst(&Instruction, 0, "", *BC.STI, errs()); - errs() << '\n'; - Instruction.dump_pretty(errs(), BC.InstPrinter.get()); - errs() << '\n'; - errs() << "BOLT-ERROR: cannot handle PC-relative operand at 0x" - << Twine::utohexstr(Address) << ". Skipping function " << *this - << ".\n"; + std::string Msg; + raw_string_ostream SS(Msg); + SS << "BOLT-ERROR: PC-relative operand can't be evaluated:\n"; + BC.InstPrinter->printInst(&Instruction, 0, "", *BC.STI, SS); + SS << '\n'; + Instruction.dump_pretty(SS, BC.InstPrinter.get()); + SS << '\n'; + SS << "BOLT-ERROR: cannot handle PC-relative operand at 0x" + << Twine::utohexstr(Address) << ". Skipping function " << *this << ".\n"; if (BC.HasRelocations) - exit(1); + return createFatalBOLTError(Msg); IsSimple = false; - return; + return createNonFatalBOLTError(Msg); } if (TargetAddress == 0 && opts::Verbosity >= 1) { - outs() << "BOLT-INFO: PC-relative operand is zero in function " << *this - << '\n'; + BC.outs() << "BOLT-INFO: PC-relative operand is zero in function " << *this + << '\n'; } const MCSymbol *TargetSymbol; @@ -1054,6 +1055,7 @@ void BinaryFunction::handlePCRelOperand(MCInst &Instruction, uint64_t Address, Instruction, TargetSymbol, static_cast(TargetOffset), &*BC.Ctx); (void)ReplaceSuccess; assert(ReplaceSuccess && "Failed to replace mem operand with symbol+off."); + return Error::success(); } MCSymbol *BinaryFunction::handleExternalReference(MCInst &Instruction, @@ -1066,9 +1068,9 @@ MCSymbol *BinaryFunction::handleExternalReference(MCInst &Instruction, const uint64_t AbsoluteInstrAddr = getAddress() + Offset; BC.addInterproceduralReference(this, TargetAddress); if (opts::Verbosity >= 2 && !IsCall && Size == 2 && !BC.HasRelocations) { - errs() << "BOLT-WARNING: relaxed tail call detected at 0x" - << Twine::utohexstr(AbsoluteInstrAddr) << " in function " << *this - << ". Code size will be increased.\n"; + BC.errs() << "BOLT-WARNING: relaxed tail call detected at 0x" + << Twine::utohexstr(AbsoluteInstrAddr) << " in function " << *this + << ". Code size will be increased.\n"; } assert(!MIB->isTailCall(Instruction) && @@ -1082,9 +1084,9 @@ MCSymbol *BinaryFunction::handleExternalReference(MCInst &Instruction, assert(MIB->isConditionalBranch(Instruction) && "unknown tail call instruction"); if (opts::Verbosity >= 2) { - errs() << "BOLT-WARNING: conditional tail call detected in " - << "function " << *this << " at 0x" - << Twine::utohexstr(AbsoluteInstrAddr) << ".\n"; + BC.errs() << "BOLT-WARNING: conditional tail call detected in " + << "function " << *this << " at 0x" + << Twine::utohexstr(AbsoluteInstrAddr) << ".\n"; } } IsCall = true; @@ -1094,8 +1096,8 @@ MCSymbol *BinaryFunction::handleExternalReference(MCInst &Instruction, // We actually see calls to address 0 in presence of weak // symbols originating from libraries. This code is never meant // to be executed. - outs() << "BOLT-INFO: Function " << *this - << " has a call to address zero.\n"; + BC.outs() << "BOLT-INFO: Function " << *this + << " has a call to address zero.\n"; } return BC.getOrCreateGlobalSymbol(TargetAddress, "FUNCat"); @@ -1164,7 +1166,7 @@ void BinaryFunction::handleAArch64IndirectCall(MCInst &Instruction, } } -bool BinaryFunction::disassemble() { +Error BinaryFunction::disassemble() { NamedRegionTimer T("disassemble", "Disassemble function", "buildfuncs", "Build Binary Functions", opts::TimeBuild); ErrorOr> ErrorOrFunctionData = getData(); @@ -1208,10 +1210,11 @@ bool BinaryFunction::disassemble() { if (isZeroPaddingAt(Offset)) break; - errs() << "BOLT-WARNING: unable to disassemble instruction at offset 0x" - << Twine::utohexstr(Offset) << " (address 0x" - << Twine::utohexstr(AbsoluteInstrAddr) << ") in function " << *this - << '\n'; + BC.errs() + << "BOLT-WARNING: unable to disassemble instruction at offset 0x" + << Twine::utohexstr(Offset) << " (address 0x" + << Twine::utohexstr(AbsoluteInstrAddr) << ") in function " << *this + << '\n'; // Some AVX-512 instructions could not be disassembled at all. if (BC.HasRelocations && opts::TrapOnAVX512 && BC.isX86()) { setTrapOnEntry(); @@ -1227,10 +1230,10 @@ bool BinaryFunction::disassemble() { if (opts::CheckEncoding && !BC.MIB->isBranch(Instruction) && !BC.MIB->isCall(Instruction) && !BC.MIB->isNoop(Instruction)) { if (!BC.validateInstructionEncoding(FunctionData.slice(Offset, Size))) { - errs() << "BOLT-WARNING: mismatching LLVM encoding detected in " - << "function " << *this << " for instruction :\n"; - BC.printInstruction(errs(), Instruction, AbsoluteInstrAddr); - errs() << '\n'; + BC.errs() << "BOLT-WARNING: mismatching LLVM encoding detected in " + << "function " << *this << " for instruction :\n"; + BC.printInstruction(BC.errs(), Instruction, AbsoluteInstrAddr); + BC.errs() << '\n'; } } @@ -1243,10 +1246,10 @@ bool BinaryFunction::disassemble() { } if (!BC.validateInstructionEncoding(FunctionData.slice(Offset, Size))) { - errs() << "BOLT-WARNING: internal assembler/disassembler error " - "detected for AVX512 instruction:\n"; - BC.printInstruction(errs(), Instruction, AbsoluteInstrAddr); - errs() << " in function " << *this << '\n'; + BC.errs() << "BOLT-WARNING: internal assembler/disassembler error " + "detected for AVX512 instruction:\n"; + BC.printInstruction(BC.errs(), Instruction, AbsoluteInstrAddr); + BC.errs() << " in function " << *this << '\n'; setIgnored(); break; } @@ -1282,9 +1285,9 @@ bool BinaryFunction::disassemble() { // function, so preserve the function as is for now. PreserveNops = true; } else { - errs() << "BOLT-WARNING: internal call detected at 0x" - << Twine::utohexstr(AbsoluteInstrAddr) << " in function " - << *this << ". Skipping.\n"; + BC.errs() << "BOLT-WARNING: internal call detected at 0x" + << Twine::utohexstr(AbsoluteInstrAddr) + << " in function " << *this << ". Skipping.\n"; IsSimple = false; } } @@ -1332,8 +1335,19 @@ bool BinaryFunction::disassemble() { if (MIB->isIndirectBranch(Instruction)) handleIndirectBranch(Instruction, Size, Offset); // Indirect call. We only need to fix it if the operand is RIP-relative. - if (IsSimple && MIB->hasPCRelOperand(Instruction)) - handlePCRelOperand(Instruction, AbsoluteInstrAddr, Size); + if (IsSimple && MIB->hasPCRelOperand(Instruction)) { + if (auto NewE = handleErrors( + handlePCRelOperand(Instruction, AbsoluteInstrAddr, Size), + [&](const BOLTError &E) -> Error { + if (E.isFatal()) + return Error(std::make_unique(std::move(E))); + if (!E.getMessage().empty()) + E.log(BC.errs()); + return Error::success(); + })) { + return Error(std::move(NewE)); + } + } if (BC.isAArch64()) handleAArch64IndirectCall(Instruction, Offset); @@ -1372,8 +1386,18 @@ bool BinaryFunction::disassemble() { UsedReloc = true; } - if (!BC.isRISCV() && MIB->hasPCRelOperand(Instruction) && !UsedReloc) - handlePCRelOperand(Instruction, AbsoluteInstrAddr, Size); + if (!BC.isRISCV() && MIB->hasPCRelOperand(Instruction) && !UsedReloc) { + if (auto NewE = handleErrors( + handlePCRelOperand(Instruction, AbsoluteInstrAddr, Size), + [&](const BOLTError &E) -> Error { + if (E.isFatal()) + return Error(std::make_unique(std::move(E))); + if (!E.getMessage().empty()) + E.log(BC.errs()); + return Error::success(); + })) + return Error(std::move(NewE)); + } } add_instruction: @@ -1413,12 +1437,12 @@ add_instruction: if (!IsSimple) { clearList(Instructions); - return false; + return createNonFatalBOLTError(""); } updateState(State::Disassembled); - return true; + return Error::success(); } bool BinaryFunction::scanExternalRefs() { @@ -1467,10 +1491,11 @@ bool BinaryFunction::scanExternalRefs() { FunctionData.slice(Offset), AbsoluteInstrAddr, nulls())) { if (opts::Verbosity >= 1 && !isZeroPaddingAt(Offset)) { - errs() << "BOLT-WARNING: unable to disassemble instruction at offset 0x" - << Twine::utohexstr(Offset) << " (address 0x" - << Twine::utohexstr(AbsoluteInstrAddr) << ") in function " - << *this << '\n'; + BC.errs() + << "BOLT-WARNING: unable to disassemble instruction at offset 0x" + << Twine::utohexstr(Offset) << " (address 0x" + << Twine::utohexstr(AbsoluteInstrAddr) << ") in function " << *this + << '\n'; } Success = false; DisassemblyFailed = true; @@ -1598,7 +1623,7 @@ bool BinaryFunction::scanExternalRefs() { HasExternalRefRelocations = true; if (opts::Verbosity >= 1 && !Success) - outs() << "BOLT-INFO: failed to scan refs for " << *this << '\n'; + BC.outs() << "BOLT-INFO: failed to scan refs for " << *this << '\n'; return Success; } @@ -1631,9 +1656,9 @@ void BinaryFunction::postProcessEntryPoints() { if (BC.isAArch64() && Offset == getSize()) continue; - errs() << "BOLT-WARNING: reference in the middle of instruction " - "detected in function " - << *this << " at offset 0x" << Twine::utohexstr(Offset) << '\n'; + BC.errs() << "BOLT-WARNING: reference in the middle of instruction " + "detected in function " + << *this << " at offset 0x" << Twine::utohexstr(Offset) << '\n'; if (BC.HasRelocations) setIgnored(); setSimple(false); @@ -1647,9 +1672,9 @@ void BinaryFunction::postProcessJumpTables() { JumpTable &JT = *JTI.second; if (JT.Type == JumpTable::JTT_PIC && opts::JumpTables == JTS_BASIC) { opts::JumpTables = JTS_MOVE; - outs() << "BOLT-INFO: forcing -jump-tables=move as PIC jump table was " - "detected in function " - << *this << '\n'; + BC.outs() << "BOLT-INFO: forcing -jump-tables=move as PIC jump table was " + "detected in function " + << *this << '\n'; } const uint64_t BDSize = BC.getBinaryDataAtAddress(JT.getAddress())->getSize(); @@ -1764,15 +1789,15 @@ bool BinaryFunction::validateExternallyReferencedOffsets() { continue; if (opts::Verbosity >= 1) { - errs() << "BOLT-WARNING: unclaimed data to code reference (possibly " - << "an unrecognized jump table entry) to " << BB->getName() - << " in " << *this << "\n"; + BC.errs() << "BOLT-WARNING: unclaimed data to code reference (possibly " + << "an unrecognized jump table entry) to " << BB->getName() + << " in " << *this << "\n"; } auto L = BC.scopeLock(); addEntryPoint(*BB); } else { - errs() << "BOLT-WARNING: unknown data to code reference to offset " - << Twine::utohexstr(Destination) << " in " << *this << "\n"; + BC.errs() << "BOLT-WARNING: unknown data to code reference to offset " + << Twine::utohexstr(Destination) << " in " << *this << "\n"; setIgnored(); } HasUnclaimedReference = true; @@ -1872,9 +1897,9 @@ bool BinaryFunction::postProcessIndirectBranches( } if (opts::Verbosity >= 2) { - outs() << "BOLT-INFO: rejected potential indirect tail call in " - << "function " << *this << " in basic block " << BB.getName() - << ".\n"; + BC.outs() << "BOLT-INFO: rejected potential indirect tail call in " + << "function " << *this << " in basic block " << BB.getName() + << ".\n"; LLVM_DEBUG(BC.printInstructions(dbgs(), BB.begin(), BB.end(), BB.getOffset(), this, true)); } @@ -1946,17 +1971,17 @@ void BinaryFunction::recomputeLandingPads() { } } -bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) { +Error BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) { auto &MIB = BC.MIB; if (!isSimple()) { assert(!BC.HasRelocations && "cannot process file with non-simple function in relocs mode"); - return false; + return createNonFatalBOLTError(""); } if (CurrentState != State::Disassembled) - return false; + return createNonFatalBOLTError(""); assert(BasicBlocks.empty() && "basic block list should be empty"); assert((Labels.find(getFirstInstructionOffset()) != Labels.end()) && @@ -2093,7 +2118,7 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) { if (BasicBlocks.empty()) { setSimple(false); - return false; + return createNonFatalBOLTError(""); } // Intermediate dump. @@ -2111,11 +2136,12 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) { BinaryBasicBlock *ToBB = getBasicBlockAtOffset(Branch.second); if (!FromBB || !ToBB) { if (!FromBB) - errs() << "BOLT-ERROR: cannot find BB containing the branch.\n"; + BC.errs() << "BOLT-ERROR: cannot find BB containing the branch.\n"; if (!ToBB) - errs() << "BOLT-ERROR: cannot find BB containing branch destination.\n"; - BC.exitWithBugReport("disassembly failed - inconsistent branch found.", - *this); + BC.errs() + << "BOLT-ERROR: cannot find BB containing branch destination.\n"; + return createFatalBOLTError(BC.generateBugReportMessage( + "disassembly failed - inconsistent branch found.", *this)); } FromBB->addSuccessor(ToBB); @@ -2193,8 +2219,8 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) { // Make any necessary adjustments for indirect branches. if (!postProcessIndirectBranches(AllocatorId)) { if (opts::Verbosity) { - errs() << "BOLT-WARNING: failed to post-process indirect branches for " - << *this << '\n'; + BC.errs() << "BOLT-WARNING: failed to post-process indirect branches for " + << *this << '\n'; } // In relocation mode we want to keep processing the function but avoid // optimizing it. @@ -2204,7 +2230,7 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) { clearList(ExternallyReferencedOffsets); clearList(UnknownIndirectBranchOffsets); - return true; + return Error::success(); } void BinaryFunction::postProcessCFG() { @@ -3034,10 +3060,6 @@ static std::string constructFilename(std::string Filename, Annotation.insert(0, "-"); if (Filename.size() + Annotation.size() + Suffix.size() > MAX_PATH) { assert(Suffix.size() + Annotation.size() <= MAX_PATH); - if (opts::Verbosity >= 1) { - errs() << "BOLT-WARNING: Filename \"" << Filename << Annotation << Suffix - << "\" exceeds the " << MAX_PATH << " size limit, truncating.\n"; - } Filename.resize(MAX_PATH - (Suffix.size() + Annotation.size())); } Filename += Annotation; @@ -3162,16 +3184,17 @@ void BinaryFunction::viewGraph() const { SmallString Filename; if (std::error_code EC = sys::fs::createTemporaryFile("bolt-cfg", "dot", Filename)) { - errs() << "BOLT-ERROR: " << EC.message() << ", unable to create " - << " bolt-cfg-XXXXX.dot temporary file.\n"; + BC.errs() << "BOLT-ERROR: " << EC.message() << ", unable to create " + << " bolt-cfg-XXXXX.dot temporary file.\n"; return; } dumpGraphToFile(std::string(Filename)); if (DisplayGraph(Filename)) - errs() << "BOLT-ERROR: Can't display " << Filename << " with graphviz.\n"; + BC.errs() << "BOLT-ERROR: Can't display " << Filename + << " with graphviz.\n"; if (std::error_code EC = sys::fs::remove(Filename)) { - errs() << "BOLT-WARNING: " << EC.message() << ", failed to remove " - << Filename << "\n"; + BC.errs() << "BOLT-WARNING: " << EC.message() << ", failed to remove " + << Filename << "\n"; } } @@ -3181,7 +3204,7 @@ void BinaryFunction::dumpGraphForPass(std::string Annotation) const { std::string Filename = constructFilename(getPrintName(), Annotation, ".dot"); if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: dumping CFG to " << Filename << "\n"; + BC.outs() << "BOLT-INFO: dumping CFG to " << Filename << "\n"; dumpGraphToFile(Filename); } @@ -3190,8 +3213,8 @@ void BinaryFunction::dumpGraphToFile(std::string Filename) const { raw_fd_ostream of(Filename, EC, sys::fs::OF_None); if (EC) { if (opts::Verbosity >= 1) { - errs() << "BOLT-WARNING: " << EC.message() << ", unable to open " - << Filename << " for output.\n"; + BC.errs() << "BOLT-WARNING: " << EC.message() << ", unable to open " + << Filename << " for output.\n"; } return; } @@ -3213,8 +3236,8 @@ bool BinaryFunction::validateCFG() const { // Make sure all blocks in CFG are valid. auto validateBlock = [this](const BinaryBasicBlock *BB, StringRef Desc) { if (!BB->isValid()) { - errs() << "BOLT-ERROR: deleted " << Desc << " " << BB->getName() - << " detected in:\n"; + BC.errs() << "BOLT-ERROR: deleted " << Desc << " " << BB->getName() + << " detected in:\n"; this->dump(); return false; } @@ -3241,8 +3264,8 @@ bool BinaryFunction::validateCFG() const { std::unordered_set BBLandingPads; for (const BinaryBasicBlock *LP : BB->landing_pads()) { if (BBLandingPads.count(LP)) { - errs() << "BOLT-ERROR: duplicate landing pad detected in" - << BB->getName() << " in function " << *this << '\n'; + BC.errs() << "BOLT-ERROR: duplicate landing pad detected in" + << BB->getName() << " in function " << *this << '\n'; return false; } BBLandingPads.insert(LP); @@ -3251,8 +3274,8 @@ bool BinaryFunction::validateCFG() const { std::unordered_set BBThrowers; for (const BinaryBasicBlock *Thrower : BB->throwers()) { if (BBThrowers.count(Thrower)) { - errs() << "BOLT-ERROR: duplicate thrower detected in" << BB->getName() - << " in function " << *this << '\n'; + BC.errs() << "BOLT-ERROR: duplicate thrower detected in" + << BB->getName() << " in function " << *this << '\n'; return false; } BBThrowers.insert(Thrower); @@ -3260,17 +3283,18 @@ bool BinaryFunction::validateCFG() const { for (const BinaryBasicBlock *LPBlock : BB->landing_pads()) { if (!llvm::is_contained(LPBlock->throwers(), BB)) { - errs() << "BOLT-ERROR: inconsistent landing pad detected in " << *this - << ": " << BB->getName() << " is in LandingPads but not in " - << LPBlock->getName() << " Throwers\n"; + BC.errs() << "BOLT-ERROR: inconsistent landing pad detected in " + << *this << ": " << BB->getName() + << " is in LandingPads but not in " << LPBlock->getName() + << " Throwers\n"; return false; } } for (const BinaryBasicBlock *Thrower : BB->throwers()) { if (!llvm::is_contained(Thrower->landing_pads(), BB)) { - errs() << "BOLT-ERROR: inconsistent thrower detected in " << *this - << ": " << BB->getName() << " is in Throwers list but not in " - << Thrower->getName() << " LandingPads\n"; + BC.errs() << "BOLT-ERROR: inconsistent thrower detected in " << *this + << ": " << BB->getName() << " is in Throwers list but not in " + << Thrower->getName() << " LandingPads\n"; return false; } } diff --git a/bolt/lib/Core/BinarySection.cpp b/bolt/lib/Core/BinarySection.cpp index 97bc25193547539daf434dfce70cfe984007b9a3..564c63e81914c33ba7c5809efeaef2ceacd857b7 100644 --- a/bolt/lib/Core/BinarySection.cpp +++ b/bolt/lib/Core/BinarySection.cpp @@ -198,7 +198,7 @@ BinarySection::~BinarySection() { if (!isAllocatable() && !hasValidSectionID() && (!hasSectionRef() || - OutputContents.data() != getContents(Section).data())) { + OutputContents.data() != getContentsOrQuit(Section).data())) { delete[] getOutputData(); } } diff --git a/bolt/lib/Core/DIEBuilder.cpp b/bolt/lib/Core/DIEBuilder.cpp index 762d3419edd340c8276df08e9f6ceb7e559b35a2..3c72c745086b5a22345b45007231a62b6d202b68 100644 --- a/bolt/lib/Core/DIEBuilder.cpp +++ b/bolt/lib/Core/DIEBuilder.cpp @@ -126,8 +126,8 @@ uint32_t DIEBuilder::allocDIE(const DWARFUnit &DU, const DWARFDie &DDie, void DIEBuilder::constructFromUnit(DWARFUnit &DU) { std::optional UnitId = getUnitId(DU); if (!UnitId) { - errs() << "BOLT-WARNING: [internal-dwarf-error]: " - << "Skip Unit at " << Twine::utohexstr(DU.getOffset()) << "\n"; + BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: " + << "Skip Unit at " << Twine::utohexstr(DU.getOffset()) << "\n"; return; } @@ -178,8 +178,9 @@ void DIEBuilder::constructFromUnit(DWARFUnit &DU) { getState().CloneUnitCtxMap[*UnitId].IsConstructed = true; } -DIEBuilder::DIEBuilder(DWARFContext *DwarfContext, bool IsDWO) - : DwarfContext(DwarfContext), IsDWO(IsDWO) {} +DIEBuilder::DIEBuilder(BinaryContext &BC, DWARFContext *DwarfContext, + bool IsDWO) + : BC(BC), DwarfContext(DwarfContext), IsDWO(IsDWO) {} static unsigned int getCUNum(DWARFContext *DwarfContext, bool IsDWO) { unsigned int CUNum = IsDWO ? DwarfContext->getNumDWOCompileUnits() @@ -475,19 +476,21 @@ DWARFDie DIEBuilder::resolveDIEReference( allocDIE(*RefCU, RefDie, getState().DIEAlloc, *UnitId); return RefDie; } - errs() << "BOLT-WARNING: [internal-dwarf-error]: invalid referenced DIE " - "at offset: " - << Twine::utohexstr(RefOffset) << ".\n"; + BC.errs() + << "BOLT-WARNING: [internal-dwarf-error]: invalid referenced DIE " + "at offset: " + << Twine::utohexstr(RefOffset) << ".\n"; } else { - errs() << "BOLT-WARNING: [internal-dwarf-error]: could not parse " - "referenced DIE at offset: " - << Twine::utohexstr(RefOffset) << ".\n"; + BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: could not parse " + "referenced DIE at offset: " + << Twine::utohexstr(RefOffset) << ".\n"; } } else { - errs() << "BOLT-WARNING: [internal-dwarf-error]: could not find referenced " - "CU. Referenced DIE offset: " - << Twine::utohexstr(RefOffset) << ".\n"; + BC.errs() + << "BOLT-WARNING: [internal-dwarf-error]: could not find referenced " + "CU. Referenced DIE offset: " + << Twine::utohexstr(RefOffset) << ".\n"; } return DWARFDie(); } @@ -516,8 +519,8 @@ void DIEBuilder::cloneDieReferenceAttribute( if (!DieInfo.Die) { assert(Ref > InputDIE.getOffset()); (void)Ref; - errs() << "BOLT-WARNING: [internal-dwarf-error]: encounter unexpected " - "unallocated DIE. Should be alloc!\n"; + BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: encounter unexpected " + "unallocated DIE. Should be alloc!\n"; // We haven't cloned this DIE yet. Just create an empty one and // store it. It'll get really cloned when we process it. DieInfo.Die = DIE::get(getState().DIEAlloc, dwarf::Tag(RefDie.getTag())); @@ -580,8 +583,8 @@ bool DIEBuilder::cloneExpression(const DataExtractor &Data, (Description.Op.size() == 2 && Description.Op[1] == Encoding::BaseTypeRef && Description.Op[0] != Encoding::Size1)) - outs() << "BOLT-WARNING: [internal-dwarf-error]: unsupported DW_OP " - "encoding.\n"; + BC.outs() << "BOLT-WARNING: [internal-dwarf-error]: unsupported DW_OP " + "encoding.\n"; if ((Description.Op.size() == 1 && Description.Op[0] == Encoding::BaseTypeRef) || @@ -616,9 +619,9 @@ bool DIEBuilder::cloneExpression(const DataExtractor &Data, Offset = Stage == CloneExpressionStage::INIT ? RefOffset : Clone->getOffset(); else - errs() << "BOLT-WARNING: [internal-dwarf-error]: base type ref " - "doesn't point to " - "DW_TAG_base_type.\n"; + BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: base type ref " + "doesn't point to " + "DW_TAG_base_type.\n"; } } uint8_t ULEB[16]; @@ -652,8 +655,9 @@ void DIEBuilder::cloneBlockAttribute( U.getVersion())) { Block = new (getState().DIEAlloc) DIEBlock; } else { - errs() << "BOLT-WARNING: [internal-dwarf-error]: Unexpected Form value in " - "cloneBlockAttribute\n"; + BC.errs() + << "BOLT-WARNING: [internal-dwarf-error]: Unexpected Form value in " + "cloneBlockAttribute\n"; return; } Attr = Loc ? static_cast(Loc) @@ -720,9 +724,9 @@ void DIEBuilder::cloneScalarAttribute( else if (auto OptionalValue = Val.getAsSectionOffset()) Value = *OptionalValue; else { - errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar " - "attribute form. Dropping " - "attribute.\n"; + BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar " + "attribute form. Dropping " + "attribute.\n"; return; } @@ -743,9 +747,9 @@ void DIEBuilder::cloneLoclistAttrubute( else if (auto OptionalValue = Val.getAsSectionOffset()) Value = OptionalValue; else - errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar " - "attribute form. Dropping " - "attribute.\n"; + BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar " + "attribute form. Dropping " + "attribute.\n"; if (!Value.has_value()) return; @@ -808,10 +812,10 @@ void DIEBuilder::cloneAttribute( cloneRefsigAttribute(Die, AttrSpec, Val); break; default: - errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported attribute " - "form " + - dwarf::FormEncodingString(AttrSpec.Form).str() + - " in cloneAttribute. Dropping."; + BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported attribute " + "form " + + dwarf::FormEncodingString(AttrSpec.Form).str() + + " in cloneAttribute. Dropping."; } } void DIEBuilder::assignAbbrev(DIEAbbrev &Abbrev) { diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp index 415b0310b6bac84c2daee8a26faea78ad850ae91..8c3f6bd2052f9eb6e0742a0eeb763518f99504e2 100644 --- a/bolt/lib/Core/DebugData.cpp +++ b/bolt/lib/Core/DebugData.cpp @@ -1185,7 +1185,7 @@ static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection, Error Err = Error::success(); const char *CStr = StrData.getCStr(&Offset, &Err); if (Err) { - errs() << "BOLT-ERROR: could not extract string from .debug_line_str"; + BC.errs() << "BOLT-ERROR: could not extract string from .debug_line_str"; continue; } const size_t NewOffset = LineStr.addString(CStr); diff --git a/bolt/lib/Core/DynoStats.cpp b/bolt/lib/Core/DynoStats.cpp index 10f076915e92d8b296e9267ac5697b2658b10ca7..5de0f9e0d6b8cd2f0f1f855ac5a8663e202482cf 100644 --- a/bolt/lib/Core/DynoStats.cpp +++ b/bolt/lib/Core/DynoStats.cpp @@ -99,7 +99,7 @@ void DynoStats::print(raw_ostream &OS, const DynoStats *Other, printStatWithDelta(Desc[Stat], Stats[Stat], Other ? (*Other)[Stat] : 0); } if (opts::PrintDynoOpcodeStat && Printer) { - outs() << "\nProgram-wide opcode histogram:\n"; + OS << "\nProgram-wide opcode histogram:\n"; OS << " Opcode, Execution Count, Max Exec Count, " "Function Name:Offset ...\n"; std::vector> SortedHistogram; diff --git a/bolt/lib/Core/Exceptions.cpp b/bolt/lib/Core/Exceptions.cpp index ab1885f6bb5851fb5a9f4d006460dce6570be8a8..54618aeb95cccbe5e9c2312296183b7aa4fb6b08 100644 --- a/bolt/lib/Core/Exceptions.cpp +++ b/bolt/lib/Core/Exceptions.cpp @@ -98,12 +98,12 @@ namespace bolt { // site table will be the same size as GCC uses uleb encodings for PC offsets. // // Note: some functions have LSDA entries with 0 call site entries. -void BinaryFunction::parseLSDA(ArrayRef LSDASectionData, - uint64_t LSDASectionAddress) { +Error BinaryFunction::parseLSDA(ArrayRef LSDASectionData, + uint64_t LSDASectionAddress) { assert(CurrentState == State::Disassembled && "unexpected function state"); if (!getLSDAAddress()) - return; + return Error::success(); DWARFDataExtractor Data( StringRef(reinterpret_cast(LSDASectionData.data()), @@ -119,9 +119,9 @@ void BinaryFunction::parseLSDA(ArrayRef LSDASectionData, std::optional MaybeLPStart = Data.getEncodedPointer( &Offset, LPStartEncoding, Offset + LSDASectionAddress); if (!MaybeLPStart) { - errs() << "BOLT-ERROR: unsupported LPStartEncoding: " - << (unsigned)LPStartEncoding << '\n'; - exit(1); + BC.errs() << "BOLT-ERROR: unsupported LPStartEncoding: " + << (unsigned)LPStartEncoding << '\n'; + return createFatalBOLTError(""); } LPStart = *MaybeLPStart; } @@ -136,13 +136,14 @@ void BinaryFunction::parseLSDA(ArrayRef LSDASectionData, } if (opts::PrintExceptions) { - outs() << "[LSDA at 0x" << Twine::utohexstr(getLSDAAddress()) - << " for function " << *this << "]:\n"; - outs() << "LPStart Encoding = 0x" << Twine::utohexstr(LPStartEncoding) - << '\n'; - outs() << "LPStart = 0x" << Twine::utohexstr(LPStart) << '\n'; - outs() << "TType Encoding = 0x" << Twine::utohexstr(TTypeEncoding) << '\n'; - outs() << "TType End = " << TTypeEnd << '\n'; + BC.outs() << "[LSDA at 0x" << Twine::utohexstr(getLSDAAddress()) + << " for function " << *this << "]:\n"; + BC.outs() << "LPStart Encoding = 0x" << Twine::utohexstr(LPStartEncoding) + << '\n'; + BC.outs() << "LPStart = 0x" << Twine::utohexstr(LPStart) << '\n'; + BC.outs() << "TType Encoding = 0x" << Twine::utohexstr(TTypeEncoding) + << '\n'; + BC.outs() << "TType End = " << TTypeEnd << '\n'; } // Table to store list of indices in type table. Entries are uleb128 values. @@ -166,9 +167,9 @@ void BinaryFunction::parseLSDA(ArrayRef LSDASectionData, uint64_t ActionTableStart = CallSiteTableEnd; if (opts::PrintExceptions) { - outs() << "CallSite Encoding = " << (unsigned)CallSiteEncoding << '\n'; - outs() << "CallSite table length = " << CallSiteTableLength << '\n'; - outs() << '\n'; + BC.outs() << "CallSite Encoding = " << (unsigned)CallSiteEncoding << '\n'; + BC.outs() << "CallSite table length = " << CallSiteTableLength << '\n'; + BC.outs() << '\n'; } this->HasEHRanges = CallSitePtr < CallSiteTableEnd; @@ -185,12 +186,13 @@ void BinaryFunction::parseLSDA(ArrayRef LSDASectionData, LandingPad += LPStart; if (opts::PrintExceptions) { - outs() << "Call Site: [0x" << Twine::utohexstr(RangeBase + Start) - << ", 0x" << Twine::utohexstr(RangeBase + Start + Length) - << "); landing pad: 0x" << Twine::utohexstr(LandingPad) - << "; action entry: 0x" << Twine::utohexstr(ActionEntry) << "\n"; - outs() << " current offset is " << (CallSitePtr - CallSiteTableStart) - << '\n'; + BC.outs() << "Call Site: [0x" << Twine::utohexstr(RangeBase + Start) + << ", 0x" << Twine::utohexstr(RangeBase + Start + Length) + << "); landing pad: 0x" << Twine::utohexstr(LandingPad) + << "; action entry: 0x" << Twine::utohexstr(ActionEntry) + << "\n"; + BC.outs() << " current offset is " << (CallSitePtr - CallSiteTableStart) + << '\n'; } // Create a handler entry if necessary. @@ -209,15 +211,16 @@ void BinaryFunction::parseLSDA(ArrayRef LSDASectionData, "BOLT-ERROR: cannot have landing pads in different functions"); setHasIndirectTargetToSplitFragment(true); BC.addFragmentsToSkip(this); - return; + return Error::success(); } const uint64_t LPOffset = LandingPad - getAddress(); if (!getInstructionAtOffset(LPOffset)) { if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: landing pad " << Twine::utohexstr(LPOffset) - << " not pointing to an instruction in function " << *this - << " - ignoring.\n"; + BC.errs() << "BOLT-WARNING: landing pad " + << Twine::utohexstr(LPOffset) + << " not pointing to an instruction in function " << *this + << " - ignoring.\n"; } else { auto Label = Labels.find(LPOffset); if (Label != Labels.end()) { @@ -271,7 +274,7 @@ void BinaryFunction::parseLSDA(ArrayRef LSDASectionData, OS << "0x" << Twine::utohexstr(TypeAddress); }; if (opts::PrintExceptions) - outs() << " actions: "; + BC.outs() << " actions: "; uint64_t ActionPtr = ActionTableStart + ActionEntry - 1; int64_t ActionType; int64_t ActionNext; @@ -281,21 +284,21 @@ void BinaryFunction::parseLSDA(ArrayRef LSDASectionData, const uint32_t Self = ActionPtr; ActionNext = Data.getSLEB128(&ActionPtr); if (opts::PrintExceptions) - outs() << Sep << "(" << ActionType << ", " << ActionNext << ") "; + BC.outs() << Sep << "(" << ActionType << ", " << ActionNext << ") "; if (ActionType == 0) { if (opts::PrintExceptions) - outs() << "cleanup"; + BC.outs() << "cleanup"; } else if (ActionType > 0) { // It's an index into a type table. MaxTypeIndex = std::max(MaxTypeIndex, static_cast(ActionType)); if (opts::PrintExceptions) { - outs() << "catch type "; - printType(ActionType, outs()); + BC.outs() << "catch type "; + printType(ActionType, BC.outs()); } } else { // ActionType < 0 if (opts::PrintExceptions) - outs() << "filter exception types "; + BC.outs() << "filter exception types "; const char *TSep = ""; // ActionType is a negative *byte* offset into *uleb128-encoded* table // of indices with base 1. @@ -305,8 +308,8 @@ void BinaryFunction::parseLSDA(ArrayRef LSDASectionData, while (uint64_t Index = Data.getULEB128(&TypeIndexTablePtr)) { MaxTypeIndex = std::max(MaxTypeIndex, static_cast(Index)); if (opts::PrintExceptions) { - outs() << TSep; - printType(Index, outs()); + BC.outs() << TSep; + printType(Index, BC.outs()); TSep = ", "; } } @@ -319,11 +322,11 @@ void BinaryFunction::parseLSDA(ArrayRef LSDASectionData, ActionPtr = Self + ActionNext; } while (ActionNext); if (opts::PrintExceptions) - outs() << '\n'; + BC.outs() << '\n'; } } if (opts::PrintExceptions) - outs() << '\n'; + BC.outs() << '\n'; assert(TypeIndexTableStart + MaxTypeIndexTableOffset <= Data.getData().size() && @@ -354,6 +357,7 @@ void BinaryFunction::parseLSDA(ArrayRef LSDASectionData, LSDATypeIndexTable = LSDASectionData.slice(TypeIndexTableStart, MaxTypeIndexTableOffset); } + return Error::success(); } void BinaryFunction::updateEHRanges() { @@ -460,7 +464,9 @@ void BinaryFunction::updateEHRanges() { const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; -CFIReaderWriter::CFIReaderWriter(const DWARFDebugFrame &EHFrame) { +CFIReaderWriter::CFIReaderWriter(BinaryContext &BC, + const DWARFDebugFrame &EHFrame) + : BC(BC) { // Prepare FDEs for fast lookup for (const dwarf::FrameEntry &Entry : EHFrame.entries()) { const auto *CurFDE = dyn_cast(&Entry); @@ -475,10 +481,10 @@ CFIReaderWriter::CFIReaderWriter(const DWARFDebugFrame &EHFrame) { if (FDEI->second->getAddressRange() == 0) { FDEI->second = CurFDE; } else if (opts::Verbosity > 0) { - errs() << "BOLT-WARNING: different FDEs for function at 0x" - << Twine::utohexstr(FDEI->first) - << " detected; sizes: " << FDEI->second->getAddressRange() - << " and " << CurFDE->getAddressRange() << '\n'; + BC.errs() << "BOLT-WARNING: different FDEs for function at 0x" + << Twine::utohexstr(FDEI->first) + << " detected; sizes: " << FDEI->second->getAddressRange() + << " and " << CurFDE->getAddressRange() << '\n'; } } } else { @@ -508,8 +514,8 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const { *CurFDE.getLinkedCIE()->getPersonalityEncoding()); } - auto decodeFrameInstruction = [&Function, &Offset, Address, CodeAlignment, - DataAlignment]( + auto decodeFrameInstruction = [this, &Function, &Offset, Address, + CodeAlignment, DataAlignment]( const CFIProgram::Instruction &Instr) { uint8_t Opcode = Instr.Opcode; if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) @@ -601,7 +607,7 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const { case DW_CFA_val_offset_sf: case DW_CFA_val_offset: if (opts::Verbosity >= 1) { - errs() << "BOLT-WARNING: DWARF val_offset() unimplemented\n"; + BC.errs() << "BOLT-WARNING: DWARF val_offset() unimplemented\n"; } return false; case DW_CFA_def_cfa_expression: @@ -622,7 +628,7 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const { } case DW_CFA_MIPS_advance_loc8: if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: DW_CFA_MIPS_advance_loc unimplemented\n"; + BC.errs() << "BOLT-WARNING: DW_CFA_MIPS_advance_loc unimplemented\n"; return false; case DW_CFA_GNU_window_save: // DW_CFA_GNU_window_save and DW_CFA_GNU_NegateRAState just use the same @@ -633,17 +639,17 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const { break; } if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: DW_CFA_GNU_window_save unimplemented\n"; + BC.errs() << "BOLT-WARNING: DW_CFA_GNU_window_save unimplemented\n"; return false; case DW_CFA_lo_user: case DW_CFA_hi_user: if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: DW_CFA_*_user unimplemented\n"; + BC.errs() << "BOLT-WARNING: DW_CFA_*_user unimplemented\n"; return false; default: if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: Unrecognized CFI instruction: " << Instr.Opcode - << '\n'; + BC.errs() << "BOLT-WARNING: Unrecognized CFI instruction: " + << Instr.Opcode << '\n'; return false; } diff --git a/bolt/lib/Core/ParallelUtilities.cpp b/bolt/lib/Core/ParallelUtilities.cpp index fb2b6dc7cd63b408b4c7e7e59238b293dea7eda9..1a28bc4346ecd565cad6c645f5673f4279d044e1 100644 --- a/bolt/lib/Core/ParallelUtilities.cpp +++ b/bolt/lib/Core/ParallelUtilities.cpp @@ -90,8 +90,9 @@ inline unsigned estimateTotalCost(const BinaryContext &BC, // Switch to trivial scheduling if total estimated work is zero if (TotalCost == 0) { - outs() << "BOLT-WARNING: Running parallel work of 0 estimated cost, will " - "switch to trivial scheduling.\n"; + BC.outs() + << "BOLT-WARNING: Running parallel work of 0 estimated cost, will " + "switch to trivial scheduling.\n"; SchedPolicy = SP_TRIVIAL; TotalCost = BC.getBinaryFunctions().size(); diff --git a/bolt/lib/Passes/ADRRelaxationPass.cpp b/bolt/lib/Passes/ADRRelaxationPass.cpp index 27a1377adef1641848188f31b55b47ac5f143764..24fddbc764cbe79dbcbd3e56a1f9324e336400dd 100644 --- a/bolt/lib/Passes/ADRRelaxationPass.cpp +++ b/bolt/lib/Passes/ADRRelaxationPass.cpp @@ -86,9 +86,10 @@ void ADRRelaxationPass::runOnFunction(BinaryFunction &BF) { // invalidate this offset, so we have to rely on linker-inserted NOP to // replace it with ADRP, and abort if it is not present. auto L = BC.scopeLock(); - errs() << formatv("BOLT-ERROR: Cannot relax adr in non-simple function " - "{0}. Use --strict option to override\n", - BF.getOneName()); + BC.errs() << formatv( + "BOLT-ERROR: Cannot relax adr in non-simple function " + "{0}. Use --strict option to override\n", + BF.getOneName()); PassFailed = true; return; } @@ -97,9 +98,9 @@ void ADRRelaxationPass::runOnFunction(BinaryFunction &BF) { } } -void ADRRelaxationPass::runOnFunctions(BinaryContext &BC) { +Error ADRRelaxationPass::runOnFunctions(BinaryContext &BC) { if (!opts::AdrPassOpt || !BC.HasRelocations) - return; + return Error::success(); ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) { runOnFunction(BF); @@ -110,7 +111,8 @@ void ADRRelaxationPass::runOnFunctions(BinaryContext &BC) { "ADRRelaxationPass"); if (PassFailed) - exit(1); + return createFatalBOLTError(""); + return Error::success(); } } // end namespace bolt diff --git a/bolt/lib/Passes/Aligner.cpp b/bolt/lib/Passes/Aligner.cpp index 7c387525434bd39bc847ebe15349784435a6ea4f..555f82a5a8178086c1d82dd2d94ad9f142937b4d 100644 --- a/bolt/lib/Passes/Aligner.cpp +++ b/bolt/lib/Passes/Aligner.cpp @@ -147,9 +147,9 @@ void AlignerPass::alignBlocks(BinaryFunction &Function, } } -void AlignerPass::runOnFunctions(BinaryContext &BC) { +Error AlignerPass::runOnFunctions(BinaryContext &BC) { if (!BC.HasRelocations) - return; + return Error::success(); AlignHistogram.resize(opts::BlockAlignment); @@ -179,6 +179,7 @@ void AlignerPass::runOnFunctions(BinaryContext &BC) { dbgs() << "BOLT-DEBUG: total execution count of aligned blocks: " << AlignedBlocksCount << '\n'; ); + return Error::success(); } } // end namespace bolt diff --git a/bolt/lib/Passes/AllocCombiner.cpp b/bolt/lib/Passes/AllocCombiner.cpp index 6d3f2a56424cb1433c2ee6b5ae426b300a7b5f17..38ef7d02a47d98f1eb1d6477d64df00b17c0ff49 100644 --- a/bolt/lib/Passes/AllocCombiner.cpp +++ b/bolt/lib/Passes/AllocCombiner.cpp @@ -103,17 +103,18 @@ void AllocCombinerPass::combineAdjustments(BinaryFunction &BF) { } } -void AllocCombinerPass::runOnFunctions(BinaryContext &BC) { +Error AllocCombinerPass::runOnFunctions(BinaryContext &BC) { if (opts::FrameOptimization == FOP_NONE) - return; + return Error::success(); runForAllWeCare(BC.getBinaryFunctions(), [&](BinaryFunction &Function) { combineAdjustments(Function); }); - outs() << "BOLT-INFO: Allocation combiner: " << NumCombined - << " empty spaces coalesced (dyn count: " << DynamicCountCombined - << ").\n"; + BC.outs() << "BOLT-INFO: Allocation combiner: " << NumCombined + << " empty spaces coalesced (dyn count: " << DynamicCountCombined + << ").\n"; + return Error::success(); } } // end namespace bolt diff --git a/bolt/lib/Passes/AsmDump.cpp b/bolt/lib/Passes/AsmDump.cpp index 18d0395cbc4ad7056512cf24fce83a665b30c84d..0a12eae8b5f7f1eb48f779ca3f347e7b3ab96cff 100644 --- a/bolt/lib/Passes/AsmDump.cpp +++ b/bolt/lib/Passes/AsmDump.cpp @@ -43,7 +43,7 @@ void dumpCFI(const BinaryFunction &BF, const MCInst &Instr, AsmPrinter &MAP) { case MCCFIInstruction::OpRememberState: case MCCFIInstruction::OpRestoreState: if (opts::Verbosity >= 2) - errs() + BF.getBinaryContext().errs() << "BOLT-WARNING: AsmDump: skipping unsupported CFI instruction in " << BF << ".\n"; @@ -102,9 +102,9 @@ void dumpFunction(const BinaryFunction &BF) { // Make sure the new directory exists, creating it if necessary. if (!opts::AsmDump.empty()) { if (std::error_code EC = sys::fs::create_directories(opts::AsmDump)) { - errs() << "BOLT-ERROR: could not create directory '" << opts::AsmDump - << "': " << EC.message() << '\n'; - exit(1); + BC.errs() << "BOLT-ERROR: could not create directory '" << opts::AsmDump + << "': " << EC.message() << '\n'; + return; } } @@ -115,14 +115,14 @@ void dumpFunction(const BinaryFunction &BF) { ? (PrintName + ".s") : (opts::AsmDump + sys::path::get_separator() + PrintName + ".s") .str(); - outs() << "BOLT-INFO: Dumping function assembly to " << Filename << "\n"; + BC.outs() << "BOLT-INFO: Dumping function assembly to " << Filename << "\n"; std::error_code EC; raw_fd_ostream OS(Filename, EC, sys::fs::OF_None); if (EC) { - errs() << "BOLT-ERROR: " << EC.message() << ", unable to open " << Filename - << " for output.\n"; - exit(1); + BC.errs() << "BOLT-ERROR: " << EC.message() << ", unable to open " + << Filename << " for output.\n"; + return; } OS.SetUnbuffered(); @@ -237,9 +237,10 @@ void dumpFunction(const BinaryFunction &BF) { dumpBinaryDataSymbols(OS, BD, LastSection); } -void AsmDumpPass::runOnFunctions(BinaryContext &BC) { +Error AsmDumpPass::runOnFunctions(BinaryContext &BC) { for (const auto &BFIt : BC.getBinaryFunctions()) dumpFunction(BFIt.second); + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Passes/BinaryFunctionCallGraph.cpp b/bolt/lib/Passes/BinaryFunctionCallGraph.cpp index 28621a4640d3e9159670f1f08f5146532add89ea..2373710c9edd629619a08f0acb9cd0bde53a3655 100644 --- a/bolt/lib/Passes/BinaryFunctionCallGraph.cpp +++ b/bolt/lib/Passes/BinaryFunctionCallGraph.cpp @@ -278,13 +278,13 @@ buildCallGraph(BinaryContext &BC, CgFilterFunction Filter, bool CgFromPerfData, bool PrintInfo = false; #endif if (PrintInfo || opts::Verbosity > 0) - outs() << format("BOLT-INFO: buildCallGraph: %u nodes, %u callsites " - "(%u recursive), density = %.6lf, %u callsites not " - "processed, %u callsites with invalid profile, " - "used perf data for %u stale functions.\n", - Cg.numNodes(), TotalCallsites, RecursiveCallsites, - Cg.density(), NotProcessed, NoProfileCallsites, - NumFallbacks); + BC.outs() << format("BOLT-INFO: buildCallGraph: %u nodes, %u callsites " + "(%u recursive), density = %.6lf, %u callsites not " + "processed, %u callsites with invalid profile, " + "used perf data for %u stale functions.\n", + Cg.numNodes(), TotalCallsites, RecursiveCallsites, + Cg.density(), NotProcessed, NoProfileCallsites, + NumFallbacks); if (opts::DumpCGDot.getNumOccurrences()) { Cg.printDot(opts::DumpCGDot, [&](CallGraph::NodeId Id) { diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp index bcb12272d1b466e0b8b769ea9845e3c268eb5ae6..d2850b03e2e13f0aab563815743a412cc31cb18f 100644 --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -301,19 +301,20 @@ void NormalizeCFG::runOnFunction(BinaryFunction &BF) { NumBlocksRemoved += NumRemoved; } -void NormalizeCFG::runOnFunctions(BinaryContext &BC) { +Error NormalizeCFG::runOnFunctions(BinaryContext &BC) { ParallelUtilities::runOnEachFunction( BC, ParallelUtilities::SchedulingPolicy::SP_BB_LINEAR, [&](BinaryFunction &BF) { runOnFunction(BF); }, [&](const BinaryFunction &BF) { return !shouldOptimize(BF); }, "NormalizeCFG"); if (NumBlocksRemoved) - outs() << "BOLT-INFO: removed " << NumBlocksRemoved << " empty block" - << (NumBlocksRemoved == 1 ? "" : "s") << '\n'; + BC.outs() << "BOLT-INFO: removed " << NumBlocksRemoved << " empty block" + << (NumBlocksRemoved == 1 ? "" : "s") << '\n'; if (NumDuplicateEdgesMerged) - outs() << "BOLT-INFO: merged " << NumDuplicateEdgesMerged - << " duplicate CFG edge" << (NumDuplicateEdgesMerged == 1 ? "" : "s") - << '\n'; + BC.outs() << "BOLT-INFO: merged " << NumDuplicateEdgesMerged + << " duplicate CFG edge" + << (NumDuplicateEdgesMerged == 1 ? "" : "s") << '\n'; + return Error::success(); } void EliminateUnreachableBlocks::runOnFunction(BinaryFunction &Function) { @@ -339,13 +340,13 @@ void EliminateUnreachableBlocks::runOnFunction(BinaryFunction &Function) { auto L = BC.scopeLock(); Modified.insert(&Function); if (opts::Verbosity > 0) - outs() << "BOLT-INFO: removed " << Count - << " dead basic block(s) accounting for " << Bytes - << " bytes in function " << Function << '\n'; + BC.outs() << "BOLT-INFO: removed " << Count + << " dead basic block(s) accounting for " << Bytes + << " bytes in function " << Function << '\n'; } } -void EliminateUnreachableBlocks::runOnFunctions(BinaryContext &BC) { +Error EliminateUnreachableBlocks::runOnFunctions(BinaryContext &BC) { ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) { runOnFunction(BF); }; @@ -359,8 +360,9 @@ void EliminateUnreachableBlocks::runOnFunctions(BinaryContext &BC) { SkipPredicate, "elimininate-unreachable"); if (DeletedBlocks) - outs() << "BOLT-INFO: UCE removed " << DeletedBlocks << " blocks and " - << DeletedBytes << " bytes of code\n"; + BC.outs() << "BOLT-INFO: UCE removed " << DeletedBlocks << " blocks and " + << DeletedBytes << " bytes of code\n"; + return Error::success(); } bool ReorderBasicBlocks::shouldPrint(const BinaryFunction &BF) const { @@ -376,9 +378,9 @@ bool ReorderBasicBlocks::shouldOptimize(const BinaryFunction &BF) const { return BinaryFunctionPass::shouldOptimize(BF); } -void ReorderBasicBlocks::runOnFunctions(BinaryContext &BC) { +Error ReorderBasicBlocks::runOnFunctions(BinaryContext &BC) { if (opts::ReorderBlocks == ReorderBasicBlocks::LT_NONE) - return; + return Error::success(); std::atomic_uint64_t ModifiedFuncCount(0); std::mutex FunctionEditDistanceMutex; @@ -411,8 +413,9 @@ void ReorderBasicBlocks::runOnFunctions(BinaryContext &BC) { const size_t NumAllProfiledFunctions = BC.NumProfiledFuncs + BC.NumStaleProfileFuncs; - outs() << "BOLT-INFO: basic block reordering modified layout of " - << format("%zu functions (%.2lf%% of profiled, %.2lf%% of total)\n", + BC.outs() << "BOLT-INFO: basic block reordering modified layout of " + << format( + "%zu functions (%.2lf%% of profiled, %.2lf%% of total)\n", ModifiedFuncCount.load(std::memory_order_relaxed), 100.0 * ModifiedFuncCount.load(std::memory_order_relaxed) / NumAllProfiledFunctions, @@ -420,7 +423,7 @@ void ReorderBasicBlocks::runOnFunctions(BinaryContext &BC) { BC.getBinaryFunctions().size()); if (opts::PrintFuncStat > 0) { - raw_ostream &OS = outs(); + raw_ostream &OS = BC.outs(); // Copy all the values into vector in order to sort them std::map ScoreMap; auto &BFs = BC.getBinaryFunctions(); @@ -452,6 +455,7 @@ void ReorderBasicBlocks::runOnFunctions(BinaryContext &BC) { << FunctionEditDistance.lookup(&Function) << "\n\n"; } } + return Error::success(); } bool ReorderBasicBlocks::modifyFunctionLayout(BinaryFunction &BF, @@ -513,7 +517,7 @@ bool ReorderBasicBlocks::modifyFunctionLayout(BinaryFunction &BF, return BF.getLayout().update(NewLayout); } -void FixupBranches::runOnFunctions(BinaryContext &BC) { +Error FixupBranches::runOnFunctions(BinaryContext &BC) { for (auto &It : BC.getBinaryFunctions()) { BinaryFunction &Function = It.second; if (!BC.shouldEmit(Function) || !Function.isSimple()) @@ -521,15 +525,18 @@ void FixupBranches::runOnFunctions(BinaryContext &BC) { Function.fixBranches(); } + return Error::success(); } -void FinalizeFunctions::runOnFunctions(BinaryContext &BC) { +Error FinalizeFunctions::runOnFunctions(BinaryContext &BC) { + std::atomic HasFatal{false}; ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) { if (!BF.finalizeCFIState()) { if (BC.HasRelocations) { - errs() << "BOLT-ERROR: unable to fix CFI state for function " << BF - << ". Exiting.\n"; - exit(1); + BC.errs() << "BOLT-ERROR: unable to fix CFI state for function " << BF + << ". Exiting.\n"; + HasFatal = true; + return; } BF.setSimple(false); return; @@ -548,17 +555,17 @@ void FinalizeFunctions::runOnFunctions(BinaryContext &BC) { ParallelUtilities::runOnEachFunction( BC, ParallelUtilities::SchedulingPolicy::SP_CONSTANT, WorkFun, SkipPredicate, "FinalizeFunctions"); + if (HasFatal) + return createFatalBOLTError("finalize CFI state failure"); + return Error::success(); } -void CheckLargeFunctions::runOnFunctions(BinaryContext &BC) { +Error CheckLargeFunctions::runOnFunctions(BinaryContext &BC) { if (BC.HasRelocations) - return; - - if (!opts::UpdateDebugSections) - return; + return Error::success(); // If the function wouldn't fit, mark it as non-simple. Otherwise, we may emit - // incorrect debug info. + // incorrect meta data. ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) { uint64_t HotSize, ColdSize; std::tie(HotSize, ColdSize) = @@ -574,6 +581,8 @@ void CheckLargeFunctions::runOnFunctions(BinaryContext &BC) { ParallelUtilities::runOnEachFunction( BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun, SkipFunc, "CheckLargeFunctions"); + + return Error::success(); } bool CheckLargeFunctions::shouldOptimize(const BinaryFunction &BF) const { @@ -581,7 +590,7 @@ bool CheckLargeFunctions::shouldOptimize(const BinaryFunction &BF) const { return BF.isSimple() && !BF.isIgnored(); } -void LowerAnnotations::runOnFunctions(BinaryContext &BC) { +Error LowerAnnotations::runOnFunctions(BinaryContext &BC) { // Convert GnuArgsSize annotations into CFIs. for (BinaryFunction *BF : BC.getAllBinaryFunctions()) { for (FunctionFragment &FF : BF->getLayout().fragments()) { @@ -607,13 +616,14 @@ void LowerAnnotations::runOnFunctions(BinaryContext &BC) { } } } + return Error::success(); } // Check for dirty state in MCSymbol objects that might be a consequence // of running calculateEmittedSize() in parallel, during split functions // pass. If an inconsistent state is found (symbol already registered or // already defined), clean it. -void CleanMCState::runOnFunctions(BinaryContext &BC) { +Error CleanMCState::runOnFunctions(BinaryContext &BC) { MCContext &Ctx = *BC.Ctx; for (const auto &SymMapEntry : Ctx.getSymbols()) { const MCSymbol *S = SymMapEntry.second; @@ -631,6 +641,7 @@ void CleanMCState::runOnFunctions(BinaryContext &BC) { dbgs() << "BOLT-DEBUG: Symbol \"" << S->getName() << "\" is variable\n"; }); } + return Error::success(); } // This peephole fixes jump instructions that jump to another basic @@ -966,9 +977,9 @@ uint64_t SimplifyConditionalTailCalls::fixTailCalls(BinaryFunction &BF) { return NumLocalCTCs > 0; } -void SimplifyConditionalTailCalls::runOnFunctions(BinaryContext &BC) { +Error SimplifyConditionalTailCalls::runOnFunctions(BinaryContext &BC) { if (!BC.isX86()) - return; + return Error::success(); for (auto &It : BC.getBinaryFunctions()) { BinaryFunction &Function = It.second; @@ -983,16 +994,17 @@ void SimplifyConditionalTailCalls::runOnFunctions(BinaryContext &BC) { } if (NumTailCallsPatched) - outs() << "BOLT-INFO: SCTC: patched " << NumTailCallsPatched - << " tail calls (" << NumOrigForwardBranches << " forward)" - << " tail calls (" << NumOrigBackwardBranches << " backward)" - << " from a total of " << NumCandidateTailCalls << " while removing " - << NumDoubleJumps << " double jumps" - << " and removing " << DeletedBlocks << " basic blocks" - << " totalling " << DeletedBytes - << " bytes of code. CTCs total execution count is " << CTCExecCount - << " and the number of times CTCs are taken is " << CTCTakenCount - << "\n"; + BC.outs() << "BOLT-INFO: SCTC: patched " << NumTailCallsPatched + << " tail calls (" << NumOrigForwardBranches << " forward)" + << " tail calls (" << NumOrigBackwardBranches << " backward)" + << " from a total of " << NumCandidateTailCalls + << " while removing " << NumDoubleJumps << " double jumps" + << " and removing " << DeletedBlocks << " basic blocks" + << " totalling " << DeletedBytes + << " bytes of code. CTCs total execution count is " + << CTCExecCount << " and the number of times CTCs are taken is " + << CTCTakenCount << "\n"; + return Error::success(); } uint64_t ShortenInstructions::shortenInstructions(BinaryFunction &Function) { @@ -1009,10 +1021,10 @@ uint64_t ShortenInstructions::shortenInstructions(BinaryFunction &Function) { if (opts::Verbosity > 2) { BC.scopeLock(); - outs() << "BOLT-INFO: shortening:\nBOLT-INFO: "; - BC.printInstruction(outs(), OriginalInst, 0, &Function); - outs() << "BOLT-INFO: to:"; - BC.printInstruction(outs(), Inst, 0, &Function); + BC.outs() << "BOLT-INFO: shortening:\nBOLT-INFO: "; + BC.printInstruction(BC.outs(), OriginalInst, 0, &Function); + BC.outs() << "BOLT-INFO: to:"; + BC.printInstruction(BC.outs(), Inst, 0, &Function); } ++Count; @@ -1022,10 +1034,10 @@ uint64_t ShortenInstructions::shortenInstructions(BinaryFunction &Function) { return Count; } -void ShortenInstructions::runOnFunctions(BinaryContext &BC) { +Error ShortenInstructions::runOnFunctions(BinaryContext &BC) { std::atomic NumShortened{0}; if (!BC.isX86()) - return; + return Error::success(); ParallelUtilities::runOnEachFunction( BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, @@ -1033,7 +1045,9 @@ void ShortenInstructions::runOnFunctions(BinaryContext &BC) { nullptr, "ShortenInstructions"); if (NumShortened) - outs() << "BOLT-INFO: " << NumShortened << " instructions were shortened\n"; + BC.outs() << "BOLT-INFO: " << NumShortened + << " instructions were shortened\n"; + return Error::success(); } void Peepholes::addTailcallTraps(BinaryFunction &Function) { @@ -1076,12 +1090,12 @@ void Peepholes::removeUselessCondBranches(BinaryFunction &Function) { } } -void Peepholes::runOnFunctions(BinaryContext &BC) { +Error Peepholes::runOnFunctions(BinaryContext &BC) { const char Opts = std::accumulate(opts::Peepholes.begin(), opts::Peepholes.end(), 0, [](const char A, const PeepholeOpts B) { return A | B; }); if (Opts == PEEP_NONE) - return; + return Error::success(); for (auto &It : BC.getBinaryFunctions()) { BinaryFunction &Function = It.second; @@ -1095,12 +1109,13 @@ void Peepholes::runOnFunctions(BinaryContext &BC) { assert(Function.validateCFG()); } } - outs() << "BOLT-INFO: Peephole: " << NumDoubleJumps - << " double jumps patched.\n" - << "BOLT-INFO: Peephole: " << TailCallTraps - << " tail call traps inserted.\n" - << "BOLT-INFO: Peephole: " << NumUselessCondBranches - << " useless conditional branches removed.\n"; + BC.outs() << "BOLT-INFO: Peephole: " << NumDoubleJumps + << " double jumps patched.\n" + << "BOLT-INFO: Peephole: " << TailCallTraps + << " tail call traps inserted.\n" + << "BOLT-INFO: Peephole: " << NumUselessCondBranches + << " useless conditional branches removed.\n"; + return Error::success(); } bool SimplifyRODataLoads::simplifyRODataLoads(BinaryFunction &BF) { @@ -1185,21 +1200,23 @@ bool SimplifyRODataLoads::simplifyRODataLoads(BinaryFunction &BF) { return NumLocalLoadsSimplified > 0; } -void SimplifyRODataLoads::runOnFunctions(BinaryContext &BC) { +Error SimplifyRODataLoads::runOnFunctions(BinaryContext &BC) { for (auto &It : BC.getBinaryFunctions()) { BinaryFunction &Function = It.second; if (shouldOptimize(Function) && simplifyRODataLoads(Function)) Modified.insert(&Function); } - outs() << "BOLT-INFO: simplified " << NumLoadsSimplified << " out of " - << NumLoadsFound << " loads from a statically computed address.\n" - << "BOLT-INFO: dynamic loads simplified: " << NumDynamicLoadsSimplified - << "\n" - << "BOLT-INFO: dynamic loads found: " << NumDynamicLoadsFound << "\n"; + BC.outs() << "BOLT-INFO: simplified " << NumLoadsSimplified << " out of " + << NumLoadsFound << " loads from a statically computed address.\n" + << "BOLT-INFO: dynamic loads simplified: " + << NumDynamicLoadsSimplified << "\n" + << "BOLT-INFO: dynamic loads found: " << NumDynamicLoadsFound + << "\n"; + return Error::success(); } -void AssignSections::runOnFunctions(BinaryContext &BC) { +Error AssignSections::runOnFunctions(BinaryContext &BC) { for (BinaryFunction *Function : BC.getInjectedBinaryFunctions()) { Function->setCodeSectionName(BC.getInjectedCodeSectionName()); Function->setColdCodeSectionName(BC.getInjectedColdCodeSectionName()); @@ -1207,7 +1224,7 @@ void AssignSections::runOnFunctions(BinaryContext &BC) { // In non-relocation mode functions have pre-assigned section names. if (!BC.HasRelocations) - return; + return Error::success(); const bool UseColdSection = BC.NumProfiledFuncs > 0 || @@ -1228,9 +1245,10 @@ void AssignSections::runOnFunctions(BinaryContext &BC) { if (Function.isSplit()) Function.setColdCodeSectionName(BC.getColdCodeSectionName()); } + return Error::success(); } -void PrintProfileStats::runOnFunctions(BinaryContext &BC) { +Error PrintProfileStats::runOnFunctions(BinaryContext &BC) { double FlowImbalanceMean = 0.0; size_t NumBlocksConsidered = 0; double WorstBias = 0.0; @@ -1314,16 +1332,17 @@ void PrintProfileStats::runOnFunctions(BinaryContext &BC) { } // Report to user - outs() << format("BOLT-INFO: Profile bias score: %.4lf%% StDev: %.4lf%%\n", - (100.0 * FlowImbalanceMean), (100.0 * FlowImbalanceVar)); + BC.outs() << format("BOLT-INFO: Profile bias score: %.4lf%% StDev: %.4lf%%\n", + (100.0 * FlowImbalanceMean), (100.0 * FlowImbalanceVar)); if (WorstBiasFunc && opts::Verbosity >= 1) { - outs() << "Worst average bias observed in " << WorstBiasFunc->getPrintName() - << "\n"; + BC.outs() << "Worst average bias observed in " + << WorstBiasFunc->getPrintName() << "\n"; LLVM_DEBUG(WorstBiasFunc->dump()); } + return Error::success(); } -void PrintProgramStats::runOnFunctions(BinaryContext &BC) { +Error PrintProgramStats::runOnFunctions(BinaryContext &BC) { uint64_t NumRegularFunctions = 0; uint64_t NumStaleProfileFunctions = 0; uint64_t NumAllStaleFunctions = 0; @@ -1354,7 +1373,7 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) { if (opts::PrintUnknownCFG) Function.dump(); else if (opts::PrintUnknown) - errs() << "function with unknown control flow: " << Function << '\n'; + BC.errs() << "function with unknown control flow: " << Function << '\n'; ++NumUnknownControlFlowFunctions; } @@ -1374,9 +1393,9 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) { } } else { if (opts::ReportStaleFuncs) { - outs() << StaleFuncsHeader; + BC.outs() << StaleFuncsHeader; StaleFuncsHeader = ""; - outs() << " " << Function << '\n'; + BC.outs() << " " << Function << '\n'; } ++NumStaleProfileFunctions; StaleSampleCount += SampleCount; @@ -1388,15 +1407,15 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) { const size_t NumAllProfiledFunctions = ProfiledFunctions.size() + NumStaleProfileFunctions; - outs() << "BOLT-INFO: " << NumAllProfiledFunctions << " out of " - << NumRegularFunctions << " functions in the binary (" - << format("%.1f", NumAllProfiledFunctions / - (float)NumRegularFunctions * 100.0f) - << "%) have non-empty execution profile\n"; + BC.outs() << "BOLT-INFO: " << NumAllProfiledFunctions << " out of " + << NumRegularFunctions << " functions in the binary (" + << format("%.1f", NumAllProfiledFunctions / + (float)NumRegularFunctions * 100.0f) + << "%) have non-empty execution profile\n"; if (NumNonSimpleProfiledFunctions) { - outs() << "BOLT-INFO: " << NumNonSimpleProfiledFunctions << " function" - << (NumNonSimpleProfiledFunctions == 1 ? "" : "s") - << " with profile could not be optimized\n"; + BC.outs() << "BOLT-INFO: " << NumNonSimpleProfiledFunctions << " function" + << (NumNonSimpleProfiledFunctions == 1 ? "" : "s") + << " with profile could not be optimized\n"; } if (NumAllStaleFunctions) { const float PctStale = @@ -1409,52 +1428,54 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) { BC.Stats.NumStaleBlocks * 100.0f; auto printErrorOrWarning = [&]() { if (PctStale > opts::StaleThreshold) - errs() << "BOLT-ERROR: "; + BC.errs() << "BOLT-ERROR: "; else - errs() << "BOLT-WARNING: "; + BC.errs() << "BOLT-WARNING: "; }; printErrorOrWarning(); - errs() << NumAllStaleFunctions - << format(" (%.1f%% of all profiled)", PctStale) << " function" - << (NumAllStaleFunctions == 1 ? "" : "s") - << " have invalid (possibly stale) profile." - " Use -report-stale to see the list.\n"; + BC.errs() << NumAllStaleFunctions + << format(" (%.1f%% of all profiled)", PctStale) << " function" + << (NumAllStaleFunctions == 1 ? "" : "s") + << " have invalid (possibly stale) profile." + " Use -report-stale to see the list.\n"; if (TotalSampleCount > 0) { printErrorOrWarning(); - errs() << (StaleSampleCount + InferredSampleCount) << " out of " - << TotalSampleCount << " samples in the binary (" - << format("%.1f", - ((100.0f * (StaleSampleCount + InferredSampleCount)) / - TotalSampleCount)) - << "%) belong to functions with invalid" - " (possibly stale) profile.\n"; + BC.errs() << (StaleSampleCount + InferredSampleCount) << " out of " + << TotalSampleCount << " samples in the binary (" + << format("%.1f", + ((100.0f * (StaleSampleCount + InferredSampleCount)) / + TotalSampleCount)) + << "%) belong to functions with invalid" + " (possibly stale) profile.\n"; } - outs() << "BOLT-INFO: " << BC.Stats.NumStaleFuncsWithEqualBlockCount - << " stale function" - << (BC.Stats.NumStaleFuncsWithEqualBlockCount == 1 ? "" : "s") - << format(" (%.1f%% of all stale)", PctStaleFuncsWithEqualBlockCount) - << " have matching block count.\n"; - outs() << "BOLT-INFO: " << BC.Stats.NumStaleBlocksWithEqualIcount - << " stale block" - << (BC.Stats.NumStaleBlocksWithEqualIcount == 1 ? "" : "s") - << format(" (%.1f%% of all stale)", PctStaleBlocksWithEqualIcount) - << " have matching icount.\n"; + BC.outs() << "BOLT-INFO: " << BC.Stats.NumStaleFuncsWithEqualBlockCount + << " stale function" + << (BC.Stats.NumStaleFuncsWithEqualBlockCount == 1 ? "" : "s") + << format(" (%.1f%% of all stale)", + PctStaleFuncsWithEqualBlockCount) + << " have matching block count.\n"; + BC.outs() << "BOLT-INFO: " << BC.Stats.NumStaleBlocksWithEqualIcount + << " stale block" + << (BC.Stats.NumStaleBlocksWithEqualIcount == 1 ? "" : "s") + << format(" (%.1f%% of all stale)", PctStaleBlocksWithEqualIcount) + << " have matching icount.\n"; if (PctStale > opts::StaleThreshold) { - errs() << "BOLT-ERROR: stale functions exceed specified threshold of " - << opts::StaleThreshold << "%. Exiting.\n"; - exit(1); + return createFatalBOLTError( + Twine("BOLT-ERROR: stale functions exceed specified threshold of ") + + Twine(opts::StaleThreshold.getValue()) + Twine("%. Exiting.\n")); } } if (NumInferredFunctions) { - outs() << format("BOLT-INFO: inferred profile for %d (%.2f%% of profiled, " - "%.2f%% of stale) functions responsible for %.2f%% samples" - " (%zu out of %zu)\n", - NumInferredFunctions, - 100.0 * NumInferredFunctions / NumAllProfiledFunctions, - 100.0 * NumInferredFunctions / NumAllStaleFunctions, - 100.0 * InferredSampleCount / TotalSampleCount, - InferredSampleCount, TotalSampleCount); - outs() << format( + BC.outs() << format( + "BOLT-INFO: inferred profile for %d (%.2f%% of profiled, " + "%.2f%% of stale) functions responsible for %.2f%% samples" + " (%zu out of %zu)\n", + NumInferredFunctions, + 100.0 * NumInferredFunctions / NumAllProfiledFunctions, + 100.0 * NumInferredFunctions / NumAllStaleFunctions, + 100.0 * InferredSampleCount / TotalSampleCount, InferredSampleCount, + TotalSampleCount); + BC.outs() << format( "BOLT-INFO: inference found an exact match for %.2f%% of basic blocks" " (%zu out of %zu stale) responsible for %.2f%% samples" " (%zu out of %zu stale)\n", @@ -1465,13 +1486,13 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) { } if (const uint64_t NumUnusedObjects = BC.getNumUnusedProfiledObjects()) { - outs() << "BOLT-INFO: profile for " << NumUnusedObjects - << " objects was ignored\n"; + BC.outs() << "BOLT-INFO: profile for " << NumUnusedObjects + << " objects was ignored\n"; } if (ProfiledFunctions.size() > 10) { if (opts::Verbosity >= 1) { - outs() << "BOLT-INFO: top called functions are:\n"; + BC.outs() << "BOLT-INFO: top called functions are:\n"; llvm::sort(ProfiledFunctions, [](const BinaryFunction *A, const BinaryFunction *B) { return B->getExecutionCount() < A->getExecutionCount(); @@ -1480,7 +1501,8 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) { auto SFIend = ProfiledFunctions.end(); for (unsigned I = 0u; I < opts::TopCalledLimit && SFI != SFIend; ++SFI, ++I) - outs() << " " << **SFI << " : " << (*SFI)->getExecutionCount() << '\n'; + BC.outs() << " " << **SFI << " : " << (*SFI)->getExecutionCount() + << '\n'; } } @@ -1520,70 +1542,70 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) { }); } - outs() << "BOLT-INFO: top functions sorted by "; + BC.outs() << "BOLT-INFO: top functions sorted by "; if (SortAll) { - outs() << "dyno stats"; + BC.outs() << "dyno stats"; } else { - outs() << "("; + BC.outs() << "("; bool PrintComma = false; for (const DynoStats::Category Category : opts::PrintSortedBy) { if (PrintComma) - outs() << ", "; - outs() << DynoStats::Description(Category); + BC.outs() << ", "; + BC.outs() << DynoStats::Description(Category); PrintComma = true; } - outs() << ")"; + BC.outs() << ")"; } - outs() << " are:\n"; + BC.outs() << " are:\n"; auto SFI = Functions.begin(); for (unsigned I = 0; I < 100 && SFI != Functions.end(); ++SFI, ++I) { const DynoStats Stats = getDynoStats(**SFI); - outs() << " " << **SFI; + BC.outs() << " " << **SFI; if (!SortAll) { - outs() << " ("; + BC.outs() << " ("; bool PrintComma = false; for (const DynoStats::Category Category : opts::PrintSortedBy) { if (PrintComma) - outs() << ", "; - outs() << dynoStatsOptName(Category) << "=" << Stats[Category]; + BC.outs() << ", "; + BC.outs() << dynoStatsOptName(Category) << "=" << Stats[Category]; PrintComma = true; } - outs() << ")"; + BC.outs() << ")"; } - outs() << "\n"; + BC.outs() << "\n"; } } if (!BC.TrappedFunctions.empty()) { - errs() << "BOLT-WARNING: " << BC.TrappedFunctions.size() << " function" - << (BC.TrappedFunctions.size() > 1 ? "s" : "") - << " will trap on entry. Use -trap-avx512=0 to disable" - " traps."; + BC.errs() << "BOLT-WARNING: " << BC.TrappedFunctions.size() << " function" + << (BC.TrappedFunctions.size() > 1 ? "s" : "") + << " will trap on entry. Use -trap-avx512=0 to disable" + " traps."; if (opts::Verbosity >= 1 || BC.TrappedFunctions.size() <= 5) { - errs() << '\n'; + BC.errs() << '\n'; for (const BinaryFunction *Function : BC.TrappedFunctions) - errs() << " " << *Function << '\n'; + BC.errs() << " " << *Function << '\n'; } else { - errs() << " Use -v=1 to see the list.\n"; + BC.errs() << " Use -v=1 to see the list.\n"; } } // Print information on missed macro-fusion opportunities seen on input. if (BC.Stats.MissedMacroFusionPairs) { - outs() << format("BOLT-INFO: the input contains %zu (dynamic count : %zu)" - " opportunities for macro-fusion optimization", - BC.Stats.MissedMacroFusionPairs, - BC.Stats.MissedMacroFusionExecCount); + BC.outs() << format( + "BOLT-INFO: the input contains %zu (dynamic count : %zu)" + " opportunities for macro-fusion optimization", + BC.Stats.MissedMacroFusionPairs, BC.Stats.MissedMacroFusionExecCount); switch (opts::AlignMacroOpFusion) { case MFT_NONE: - outs() << ". Use -align-macro-fusion to fix.\n"; + BC.outs() << ". Use -align-macro-fusion to fix.\n"; break; case MFT_HOT: - outs() << ". Will fix instances on a hot path.\n"; + BC.outs() << ". Will fix instances on a hot path.\n"; break; case MFT_ALL: - outs() << " that are going to be fixed\n"; + BC.outs() << " that are going to be fixed\n"; break; } } @@ -1618,36 +1640,38 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) { B->getKnownExecutionCount() / B->getSize(); }); - outs() << "BOLT-INFO: " << SuboptimalFuncs.size() - << " functions have " - "cold code in the middle of hot code. Top functions are:\n"; + BC.outs() << "BOLT-INFO: " << SuboptimalFuncs.size() + << " functions have " + "cold code in the middle of hot code. Top functions are:\n"; for (unsigned I = 0; I < std::min(static_cast(opts::ReportBadLayout), SuboptimalFuncs.size()); ++I) - SuboptimalFuncs[I]->print(outs()); + SuboptimalFuncs[I]->print(BC.outs()); } } if (NumUnknownControlFlowFunctions) { - outs() << "BOLT-INFO: " << NumUnknownControlFlowFunctions - << " functions have instructions with unknown control flow"; + BC.outs() << "BOLT-INFO: " << NumUnknownControlFlowFunctions + << " functions have instructions with unknown control flow"; if (!opts::PrintUnknown) - outs() << ". Use -print-unknown to see the list."; - outs() << '\n'; + BC.outs() << ". Use -print-unknown to see the list."; + BC.outs() << '\n'; } + return Error::success(); } -void InstructionLowering::runOnFunctions(BinaryContext &BC) { +Error InstructionLowering::runOnFunctions(BinaryContext &BC) { for (auto &BFI : BC.getBinaryFunctions()) for (BinaryBasicBlock &BB : BFI.second) for (MCInst &Instruction : BB) BC.MIB->lowerTailCall(Instruction); + return Error::success(); } -void StripRepRet::runOnFunctions(BinaryContext &BC) { +Error StripRepRet::runOnFunctions(BinaryContext &BC) { if (!BC.isX86()) - return; + return Error::success(); uint64_t NumPrefixesRemoved = 0; uint64_t NumBytesSaved = 0; @@ -1664,15 +1688,16 @@ void StripRepRet::runOnFunctions(BinaryContext &BC) { } if (NumBytesSaved) - outs() << "BOLT-INFO: removed " << NumBytesSaved - << " 'repz' prefixes" - " with estimated execution count of " - << NumPrefixesRemoved << " times.\n"; + BC.outs() << "BOLT-INFO: removed " << NumBytesSaved + << " 'repz' prefixes" + " with estimated execution count of " + << NumPrefixesRemoved << " times.\n"; + return Error::success(); } -void InlineMemcpy::runOnFunctions(BinaryContext &BC) { +Error InlineMemcpy::runOnFunctions(BinaryContext &BC) { if (!BC.isX86()) - return; + return Error::success(); uint64_t NumInlined = 0; uint64_t NumInlinedDyno = 0; @@ -1711,12 +1736,13 @@ void InlineMemcpy::runOnFunctions(BinaryContext &BC) { } if (NumInlined) { - outs() << "BOLT-INFO: inlined " << NumInlined << " memcpy() calls"; + BC.outs() << "BOLT-INFO: inlined " << NumInlined << " memcpy() calls"; if (NumInlinedDyno) - outs() << ". The calls were executed " << NumInlinedDyno - << " times based on profile."; - outs() << '\n'; + BC.outs() << ". The calls were executed " << NumInlinedDyno + << " times based on profile."; + BC.outs() << '\n'; } + return Error::success(); } bool SpecializeMemcpy1::shouldOptimize(const BinaryFunction &Function) const { @@ -1757,9 +1783,9 @@ std::set SpecializeMemcpy1::getCallSitesToOptimize( return Sites; } -void SpecializeMemcpy1::runOnFunctions(BinaryContext &BC) { +Error SpecializeMemcpy1::runOnFunctions(BinaryContext &BC) { if (!BC.isX86()) - return; + return Error::success(); uint64_t NumSpecialized = 0; uint64_t NumSpecializedDyno = 0; @@ -1844,13 +1870,14 @@ void SpecializeMemcpy1::runOnFunctions(BinaryContext &BC) { } if (NumSpecialized) { - outs() << "BOLT-INFO: specialized " << NumSpecialized - << " memcpy() call sites for size 1"; + BC.outs() << "BOLT-INFO: specialized " << NumSpecialized + << " memcpy() call sites for size 1"; if (NumSpecializedDyno) - outs() << ". The calls were executed " << NumSpecializedDyno - << " times based on profile."; - outs() << '\n'; + BC.outs() << ". The calls were executed " << NumSpecializedDyno + << " times based on profile."; + BC.outs() << '\n'; } + return Error::success(); } void RemoveNops::runOnFunction(BinaryFunction &BF) { @@ -1864,7 +1891,7 @@ void RemoveNops::runOnFunction(BinaryFunction &BF) { } } -void RemoveNops::runOnFunctions(BinaryContext &BC) { +Error RemoveNops::runOnFunctions(BinaryContext &BC) { ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) { runOnFunction(BF); }; @@ -1876,6 +1903,7 @@ void RemoveNops::runOnFunctions(BinaryContext &BC) { ParallelUtilities::runOnEachFunction( BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun, SkipFunc, "RemoveNops"); + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Passes/CMOVConversion.cpp b/bolt/lib/Passes/CMOVConversion.cpp index 6213479a5090ae67fe16f2c1d8f293ffa0988153..2492ff21794634bd35bc4f7f03c9970bccf69739 100644 --- a/bolt/lib/Passes/CMOVConversion.cpp +++ b/bolt/lib/Passes/CMOVConversion.cpp @@ -168,14 +168,14 @@ int calculateConditionBias(const BinaryBasicBlock &BB, return -1; } -void CMOVConversion::Stats::dump() { - outs() << "converted static " << StaticPerformed << "/" << StaticPossible - << formatv(" ({0:P}) ", getStaticRatio()) - << "hammock(s) into CMOV sequences, with dynamic execution count " - << DynamicPerformed << "/" << DynamicPossible - << formatv(" ({0:P}), ", getDynamicRatio()) << "saving " << RemovedMP - << "/" << PossibleMP << formatv(" ({0:P}) ", getMPRatio()) - << "mispredictions\n"; +void CMOVConversion::Stats::dumpTo(raw_ostream &OS) { + OS << "converted static " << StaticPerformed << "/" << StaticPossible + << formatv(" ({0:P}) ", getStaticRatio()) + << "hammock(s) into CMOV sequences, with dynamic execution count " + << DynamicPerformed << "/" << DynamicPossible + << formatv(" ({0:P}), ", getDynamicRatio()) << "saving " << RemovedMP + << "/" << PossibleMP << formatv(" ({0:P}) ", getMPRatio()) + << "mispredictions\n"; } void CMOVConversion::runOnFunction(BinaryFunction &Function) { @@ -265,13 +265,13 @@ void CMOVConversion::runOnFunction(BinaryFunction &Function) { if (Modified) Function.eraseInvalidBBs(); if (opts::Verbosity > 1) { - outs() << "BOLT-INFO: CMOVConversion: " << Function << ", "; - Local.dump(); + BC.outs() << "BOLT-INFO: CMOVConversion: " << Function << ", "; + Local.dumpTo(BC.outs()); } Global = Global + Local; } -void CMOVConversion::runOnFunctions(BinaryContext &BC) { +Error CMOVConversion::runOnFunctions(BinaryContext &BC) { for (auto &It : BC.getBinaryFunctions()) { BinaryFunction &Function = It.second; if (!shouldOptimize(Function)) @@ -279,8 +279,9 @@ void CMOVConversion::runOnFunctions(BinaryContext &BC) { runOnFunction(Function); } - outs() << "BOLT-INFO: CMOVConversion total: "; - Global.dump(); + BC.outs() << "BOLT-INFO: CMOVConversion total: "; + Global.dumpTo(BC.outs()); + return Error::success(); } } // end namespace bolt diff --git a/bolt/lib/Passes/CacheMetrics.cpp b/bolt/lib/Passes/CacheMetrics.cpp index f6708997a43350d0d005fa3ed0d9132a69fac586..b02d4303110b37392ff1115254827b194a8b18fd 100644 --- a/bolt/lib/Passes/CacheMetrics.cpp +++ b/bolt/lib/Passes/CacheMetrics.cpp @@ -189,7 +189,8 @@ double expectedCacheHitRatio( } // namespace -void CacheMetrics::printAll(const std::vector &BFs) { +void CacheMetrics::printAll(raw_ostream &OS, + const std::vector &BFs) { // Stats related to hot-cold code splitting size_t NumFunctions = 0; size_t NumProfiledFunctions = 0; @@ -222,36 +223,36 @@ void CacheMetrics::printAll(const std::vector &BFs) { } } - outs() << format(" There are %zu functions;", NumFunctions) - << format(" %zu (%.2lf%%) are in the hot section,", NumHotFunctions, - 100.0 * NumHotFunctions / NumFunctions) - << format(" %zu (%.2lf%%) have profile\n", NumProfiledFunctions, - 100.0 * NumProfiledFunctions / NumFunctions); - outs() << format(" There are %zu basic blocks;", NumBlocks) - << format(" %zu (%.2lf%%) are in the hot section\n", NumHotBlocks, - 100.0 * NumHotBlocks / NumBlocks); + OS << format(" There are %zu functions;", NumFunctions) + << format(" %zu (%.2lf%%) are in the hot section,", NumHotFunctions, + 100.0 * NumHotFunctions / NumFunctions) + << format(" %zu (%.2lf%%) have profile\n", NumProfiledFunctions, + 100.0 * NumProfiledFunctions / NumFunctions); + OS << format(" There are %zu basic blocks;", NumBlocks) + << format(" %zu (%.2lf%%) are in the hot section\n", NumHotBlocks, + 100.0 * NumHotBlocks / NumBlocks); assert(TotalCodeMinAddr <= TotalCodeMaxAddr && "incorrect output addresses"); size_t HotCodeSize = HotCodeMaxAddr - HotCodeMinAddr; size_t TotalCodeSize = TotalCodeMaxAddr - TotalCodeMinAddr; size_t HugePage2MB = 2 << 20; - outs() << format(" Hot code takes %.2lf%% of binary (%zu bytes out of %zu, " - "%.2lf huge pages)\n", - 100.0 * HotCodeSize / TotalCodeSize, HotCodeSize, - TotalCodeSize, double(HotCodeSize) / HugePage2MB); + OS << format(" Hot code takes %.2lf%% of binary (%zu bytes out of %zu, " + "%.2lf huge pages)\n", + 100.0 * HotCodeSize / TotalCodeSize, HotCodeSize, TotalCodeSize, + double(HotCodeSize) / HugePage2MB); // Stats related to expected cache performance std::unordered_map BBAddr; std::unordered_map BBSize; extractBasicBlockInfo(BFs, BBAddr, BBSize); - outs() << " Expected i-TLB cache hit ratio: " - << format("%.2lf%%\n", expectedCacheHitRatio(BFs, BBAddr, BBSize)); + OS << " Expected i-TLB cache hit ratio: " + << format("%.2lf%%\n", expectedCacheHitRatio(BFs, BBAddr, BBSize)); auto Stats = calcTSPScore(BFs, BBAddr, BBSize); - outs() << " TSP score: " - << format("%.2lf%% (%zu out of %zu)\n", - 100.0 * Stats.first / std::max(Stats.second, 1), - Stats.first, Stats.second); + OS << " TSP score: " + << format("%.2lf%% (%zu out of %zu)\n", + 100.0 * Stats.first / std::max(Stats.second, 1), + Stats.first, Stats.second); } diff --git a/bolt/lib/Passes/FixRISCVCallsPass.cpp b/bolt/lib/Passes/FixRISCVCallsPass.cpp index e2984deda16dc3eb04921ee9e063c3c2150298d0..83c745facb290b70209a3243fdf4a553ca49f3e4 100644 --- a/bolt/lib/Passes/FixRISCVCallsPass.cpp +++ b/bolt/lib/Passes/FixRISCVCallsPass.cpp @@ -68,9 +68,9 @@ void FixRISCVCallsPass::runOnFunction(BinaryFunction &BF) { } } -void FixRISCVCallsPass::runOnFunctions(BinaryContext &BC) { +Error FixRISCVCallsPass::runOnFunctions(BinaryContext &BC) { if (!BC.isRISCV() || !BC.HasRelocations) - return; + return Error::success(); ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) { runOnFunction(BF); @@ -79,6 +79,8 @@ void FixRISCVCallsPass::runOnFunctions(BinaryContext &BC) { ParallelUtilities::runOnEachFunction( BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun, nullptr, "FixRISCVCalls"); + + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Passes/FixRelaxationPass.cpp b/bolt/lib/Passes/FixRelaxationPass.cpp index 3dd19b6b43b76752381212f08292b1c5a097e598..a49fb9894e808cccdf0f222a51e6f354db2c0f8d 100644 --- a/bolt/lib/Passes/FixRelaxationPass.cpp +++ b/bolt/lib/Passes/FixRelaxationPass.cpp @@ -47,9 +47,9 @@ void FixRelaxations::runOnFunction(BinaryFunction &BF) { } } -void FixRelaxations::runOnFunctions(BinaryContext &BC) { +Error FixRelaxations::runOnFunctions(BinaryContext &BC) { if (!BC.isAArch64() || !BC.HasRelocations) - return; + return Error::success(); ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) { runOnFunction(BF); @@ -58,6 +58,7 @@ void FixRelaxations::runOnFunctions(BinaryContext &BC) { ParallelUtilities::runOnEachFunction( BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun, nullptr, "FixRelaxations"); + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Passes/FrameAnalysis.cpp b/bolt/lib/Passes/FrameAnalysis.cpp index 1e6be498a4790c0c90edbd8c3188e8699014ebf1..7f1245e39f567b933ade802d06597c09f6edfe56 100644 --- a/bolt/lib/Passes/FrameAnalysis.cpp +++ b/bolt/lib/Passes/FrameAnalysis.cpp @@ -124,7 +124,7 @@ class FrameAccessAnalysis { if (IsIndexed || (!FIE.Size && (FIE.IsLoad || FIE.IsStore))) { LLVM_DEBUG(dbgs() << "Giving up on indexed memory access/unknown size\n"); LLVM_DEBUG(dbgs() << "Blame insn: "); - LLVM_DEBUG(BC.printInstruction(outs(), Inst, 0, &BF, true, false, false)); + LLVM_DEBUG(BC.printInstruction(dbgs(), Inst, 0, &BF, true, false, false)); LLVM_DEBUG(Inst.dump()); return false; } @@ -570,13 +570,14 @@ FrameAnalysis::FrameAnalysis(BinaryContext &BC, BinaryFunctionCallGraph &CG) } void FrameAnalysis::printStats() { - outs() << "BOLT-INFO: FRAME ANALYSIS: " << NumFunctionsNotOptimized - << " function(s) were not optimized.\n" - << "BOLT-INFO: FRAME ANALYSIS: " << NumFunctionsFailedRestoreFI - << " function(s) " - << format("(%.1lf%% dyn cov)", + BC.outs() << "BOLT-INFO: FRAME ANALYSIS: " << NumFunctionsNotOptimized + << " function(s) were not optimized.\n" + << "BOLT-INFO: FRAME ANALYSIS: " << NumFunctionsFailedRestoreFI + << " function(s) " + << format( + "(%.1lf%% dyn cov)", (100.0 * CountFunctionsFailedRestoreFI / CountDenominator)) - << " could not have its frame indices restored.\n"; + << " could not have its frame indices restored.\n"; } void FrameAnalysis::clearSPTMap() { diff --git a/bolt/lib/Passes/FrameOptimizer.cpp b/bolt/lib/Passes/FrameOptimizer.cpp index 6f6dea08950a7dd1ba425e3824b9bc36646f447c..fb5f8eafa5cf846e576bbfff6b4f7b1ddbec5b06 100644 --- a/bolt/lib/Passes/FrameOptimizer.cpp +++ b/bolt/lib/Passes/FrameOptimizer.cpp @@ -221,9 +221,9 @@ void FrameOptimizerPass::removeUnusedStores(const FrameAnalysis &FA, LLVM_DEBUG(dbgs() << "FOP modified \"" << BF.getPrintName() << "\"\n"); } -void FrameOptimizerPass::runOnFunctions(BinaryContext &BC) { +Error FrameOptimizerPass::runOnFunctions(BinaryContext &BC) { if (opts::FrameOptimization == FOP_NONE) - return; + return Error::success(); std::unique_ptr CG; std::unique_ptr FA; @@ -285,29 +285,31 @@ void FrameOptimizerPass::runOnFunctions(BinaryContext &BC) { { NamedRegionTimer T1("shrinkwrapping", "shrink wrapping", "FOP", "FOP breakdown", opts::TimeOpts); - performShrinkWrapping(*RA, *FA, BC); + if (Error E = performShrinkWrapping(*RA, *FA, BC)) + return Error(std::move(E)); } - outs() << "BOLT-INFO: FOP optimized " << NumRedundantLoads - << " redundant load(s) and " << NumRedundantStores - << " unused store(s)\n"; - outs() << "BOLT-INFO: Frequency of redundant loads is " << FreqRedundantLoads - << " and frequency of unused stores is " << FreqRedundantStores - << "\n"; - outs() << "BOLT-INFO: Frequency of loads changed to use a register is " - << FreqLoadsChangedToReg - << " and frequency of loads changed to use an immediate is " - << FreqLoadsChangedToImm << "\n"; - outs() << "BOLT-INFO: FOP deleted " << NumLoadsDeleted - << " load(s) (dyn count: " << FreqLoadsDeleted << ") and " - << NumRedundantStores << " store(s)\n"; + BC.outs() << "BOLT-INFO: FOP optimized " << NumRedundantLoads + << " redundant load(s) and " << NumRedundantStores + << " unused store(s)\n"; + BC.outs() << "BOLT-INFO: Frequency of redundant loads is " + << FreqRedundantLoads << " and frequency of unused stores is " + << FreqRedundantStores << "\n"; + BC.outs() << "BOLT-INFO: Frequency of loads changed to use a register is " + << FreqLoadsChangedToReg + << " and frequency of loads changed to use an immediate is " + << FreqLoadsChangedToImm << "\n"; + BC.outs() << "BOLT-INFO: FOP deleted " << NumLoadsDeleted + << " load(s) (dyn count: " << FreqLoadsDeleted << ") and " + << NumRedundantStores << " store(s)\n"; FA->printStats(); - ShrinkWrapping::printStats(); + ShrinkWrapping::printStats(BC); + return Error::success(); } -void FrameOptimizerPass::performShrinkWrapping(const RegAnalysis &RA, - const FrameAnalysis &FA, - BinaryContext &BC) { +Error FrameOptimizerPass::performShrinkWrapping(const RegAnalysis &RA, + const FrameAnalysis &FA, + BinaryContext &BC) { // Initialize necessary annotations to allow safe parallel accesses to // annotation index in MIB BC.MIB->getOrCreateAnnotationIndex(CalleeSavedAnalysis::getSaveTagName()); @@ -357,12 +359,21 @@ void FrameOptimizerPass::performShrinkWrapping(const RegAnalysis &RA, const bool HotOnly = opts::FrameOptimization == FOP_HOT; + Error SWError = Error::success(); + ParallelUtilities::WorkFuncWithAllocTy WorkFunction = [&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocatorId) { DataflowInfoManager Info(BF, &RA, &FA, AllocatorId); ShrinkWrapping SW(FA, BF, Info, AllocatorId); - if (SW.perform(HotOnly)) { + auto ChangedOrErr = SW.perform(HotOnly); + if (auto E = ChangedOrErr.takeError()) { + std::lock_guard Lock(FuncsChangedMutex); + SWError = joinErrors(std::move(SWError), Error(std::move(E))); + return; + } + const bool Changed = *ChangedOrErr; + if (Changed) { std::lock_guard Lock(FuncsChangedMutex); FuncsChanged.insert(&BF); LLVM_DEBUG(LogFunc(BF)); @@ -374,10 +385,11 @@ void FrameOptimizerPass::performShrinkWrapping(const RegAnalysis &RA, SkipPredicate, "shrink-wrapping"); if (!Top10Funcs.empty()) { - outs() << "BOLT-INFO: top 10 functions changed by shrink wrapping:\n"; + BC.outs() << "BOLT-INFO: top 10 functions changed by shrink wrapping:\n"; for (const auto &Elmt : Top10Funcs) - outs() << Elmt.first << " : " << Elmt.second->getPrintName() << "\n"; + BC.outs() << Elmt.first << " : " << Elmt.second->getPrintName() << "\n"; } + return SWError; } } // namespace bolt diff --git a/bolt/lib/Passes/Hugify.cpp b/bolt/lib/Passes/Hugify.cpp index d2a64fb97c196d1f02cc211b9046d3f5fd16bd2b..b77356153bfd8caf5f1e01b27c29547c3b45a704 100644 --- a/bolt/lib/Passes/Hugify.cpp +++ b/bolt/lib/Passes/Hugify.cpp @@ -16,10 +16,10 @@ using namespace llvm; namespace llvm { namespace bolt { -void HugePage::runOnFunctions(BinaryContext &BC) { +Error HugePage::runOnFunctions(BinaryContext &BC) { auto *RtLibrary = BC.getRuntimeLibrary(); if (!RtLibrary || !BC.isELF() || !BC.StartFunctionAddress) { - return; + return Error::success(); } auto createSimpleFunction = @@ -45,6 +45,7 @@ void HugePage::runOnFunctions(BinaryContext &BC) { const MCSymbol *StartSym = Start->getSymbol(); createSimpleFunction("__bolt_hugify_start_program", BC.MIB->createSymbolTrampoline(StartSym, BC.Ctx.get())); + return Error::success(); } } // namespace bolt } // namespace llvm diff --git a/bolt/lib/Passes/IdenticalCodeFolding.cpp b/bolt/lib/Passes/IdenticalCodeFolding.cpp index dfbc72e48e5d285b1e38814d0531d0628615b1b0..9f8d82b05ccf48522197ed6884def81dc2dddee1 100644 --- a/bolt/lib/Passes/IdenticalCodeFolding.cpp +++ b/bolt/lib/Passes/IdenticalCodeFolding.cpp @@ -341,7 +341,7 @@ typedef std::unordered_map, namespace llvm { namespace bolt { -void IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) { +Error IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) { const size_t OriginalFunctionCount = BC.getBinaryFunctions().size(); uint64_t NumFunctionsFolded = 0; std::atomic NumJTFunctionsFolded{0}; @@ -508,14 +508,16 @@ void IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) { }); if (NumFunctionsFolded) - outs() << "BOLT-INFO: ICF folded " << NumFunctionsFolded << " out of " - << OriginalFunctionCount << " functions in " << Iteration - << " passes. " << NumJTFunctionsFolded - << " functions had jump tables.\n" - << "BOLT-INFO: Removing all identical functions will save " - << format("%.2lf", (double)BytesSavedEstimate / 1024) - << " KB of code space. Folded functions were called " << NumCalled - << " times based on profile.\n"; + BC.outs() << "BOLT-INFO: ICF folded " << NumFunctionsFolded << " out of " + << OriginalFunctionCount << " functions in " << Iteration + << " passes. " << NumJTFunctionsFolded + << " functions had jump tables.\n" + << "BOLT-INFO: Removing all identical functions will save " + << format("%.2lf", (double)BytesSavedEstimate / 1024) + << " KB of code space. Folded functions were called " << NumCalled + << " times based on profile.\n"; + + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Passes/IndirectCallPromotion.cpp b/bolt/lib/Passes/IndirectCallPromotion.cpp index 451758161ef5e69ed69608b0b86bf8a60fcc9706..55eede641fd2f7ac49c4c6d730ee87ab8b7e8f59 100644 --- a/bolt/lib/Passes/IndirectCallPromotion.cpp +++ b/bolt/lib/Passes/IndirectCallPromotion.cpp @@ -171,9 +171,10 @@ static bool verifyProfile(std::map &BFs) { if (BI->Count != BinaryBasicBlock::COUNT_NO_PROFILE && BI->Count > 0) { if (BB.getKnownExecutionCount() == 0 || SuccBB->getKnownExecutionCount() == 0) { - errs() << "BOLT-WARNING: profile verification failed after ICP for " - "function " - << BF << '\n'; + BF.getBinaryContext().errs() + << "BOLT-WARNING: profile verification failed after ICP for " + "function " + << BF << '\n'; IsValid = false; } } @@ -526,6 +527,7 @@ IndirectCallPromotion::findCallTargetSymbols(std::vector &Targets, size_t &N, BinaryBasicBlock &BB, MCInst &CallInst, MCInst *&TargetFetchInst) const { + const BinaryContext &BC = BB.getFunction()->getBinaryContext(); const JumpTable *JT = BB.getFunction()->getJumpTable(CallInst); SymTargetsType SymTargets; @@ -556,8 +558,9 @@ IndirectCallPromotion::findCallTargetSymbols(std::vector &Targets, if (!HotTargets.empty()) { if (opts::Verbosity >= 1) for (size_t I = 0; I < HotTargets.size(); ++I) - outs() << "BOLT-INFO: HotTarget[" << I << "] = (" << HotTargets[I].first - << ", " << HotTargets[I].second << ")\n"; + BC.outs() << "BOLT-INFO: HotTarget[" << I << "] = (" + << HotTargets[I].first << ", " << HotTargets[I].second + << ")\n"; // Recompute hottest targets, now discriminating which index is hot // NOTE: This is a tradeoff. On one hand, we get index information. On the @@ -611,9 +614,9 @@ IndirectCallPromotion::findCallTargetSymbols(std::vector &Targets, N = I; if (N == 0 && opts::Verbosity >= 1) { - outs() << "BOLT-INFO: ICP failed in " << *BB.getFunction() << " in " - << BB.getName() << ": failed to meet thresholds after memory " - << "profile data was loaded.\n"; + BC.outs() << "BOLT-INFO: ICP failed in " << *BB.getFunction() << " in " + << BB.getName() << ": failed to meet thresholds after memory " + << "profile data was loaded.\n"; return SymTargets; } } @@ -974,9 +977,9 @@ size_t IndirectCallPromotion::canPromoteCallsite( if (Targets.empty() || !NumCalls) { if (opts::Verbosity >= 1) { const ptrdiff_t InstIdx = &Inst - &(*BB.begin()); - outs() << "BOLT-INFO: ICP failed in " << *BF << " @ " << InstIdx << " in " - << BB.getName() << ", calls = " << NumCalls - << ", targets empty or NumCalls == 0.\n"; + BC.outs() << "BOLT-INFO: ICP failed in " << *BF << " @ " << InstIdx + << " in " << BB.getName() << ", calls = " << NumCalls + << ", targets empty or NumCalls == 0.\n"; } return 0; } @@ -1015,10 +1018,10 @@ size_t IndirectCallPromotion::canPromoteCallsite( if (TopNFrequency == 0 || TopNFrequency < opts::ICPMispredictThreshold) { if (opts::Verbosity >= 1) { const ptrdiff_t InstIdx = &Inst - &(*BB.begin()); - outs() << "BOLT-INFO: ICP failed in " << *BF << " @ " << InstIdx - << " in " << BB.getName() << ", calls = " << NumCalls - << ", top N mis. frequency " << format("%.1f", TopNFrequency) - << "% < " << opts::ICPMispredictThreshold << "%\n"; + BC.outs() << "BOLT-INFO: ICP failed in " << *BF << " @ " << InstIdx + << " in " << BB.getName() << ", calls = " << NumCalls + << ", top N mis. frequency " << format("%.1f", TopNFrequency) + << "% < " << opts::ICPMispredictThreshold << "%\n"; } return 0; } @@ -1061,11 +1064,11 @@ size_t IndirectCallPromotion::canPromoteCallsite( if (TopNMispredictFrequency < opts::ICPMispredictThreshold) { if (opts::Verbosity >= 1) { const ptrdiff_t InstIdx = &Inst - &(*BB.begin()); - outs() << "BOLT-INFO: ICP failed in " << *BF << " @ " << InstIdx - << " in " << BB.getName() << ", calls = " << NumCalls - << ", top N mispredict frequency " - << format("%.1f", TopNMispredictFrequency) << "% < " - << opts::ICPMispredictThreshold << "%\n"; + BC.outs() << "BOLT-INFO: ICP failed in " << *BF << " @ " << InstIdx + << " in " << BB.getName() << ", calls = " << NumCalls + << ", top N mispredict frequency " + << format("%.1f", TopNMispredictFrequency) << "% < " + << opts::ICPMispredictThreshold << "%\n"; } return 0; } @@ -1106,29 +1109,29 @@ void IndirectCallPromotion::printCallsiteInfo( const bool IsJumpTable = BB.getFunction()->getJumpTable(Inst); const ptrdiff_t InstIdx = &Inst - &(*BB.begin()); - outs() << "BOLT-INFO: ICP candidate branch info: " << *BB.getFunction() - << " @ " << InstIdx << " in " << BB.getName() - << " -> calls = " << NumCalls - << (IsTailCall ? " (tail)" : (IsJumpTable ? " (jump table)" : "")) - << "\n"; + BC.outs() << "BOLT-INFO: ICP candidate branch info: " << *BB.getFunction() + << " @ " << InstIdx << " in " << BB.getName() + << " -> calls = " << NumCalls + << (IsTailCall ? " (tail)" : (IsJumpTable ? " (jump table)" : "")) + << "\n"; for (size_t I = 0; I < N; I++) { const double Frequency = 100.0 * Targets[I].Branches / NumCalls; const double MisFrequency = 100.0 * Targets[I].Mispreds / NumCalls; - outs() << "BOLT-INFO: "; + BC.outs() << "BOLT-INFO: "; if (Targets[I].To.Sym) - outs() << Targets[I].To.Sym->getName(); + BC.outs() << Targets[I].To.Sym->getName(); else - outs() << Targets[I].To.Addr; - outs() << ", calls = " << Targets[I].Branches - << ", mispreds = " << Targets[I].Mispreds - << ", taken freq = " << format("%.1f", Frequency) << "%" - << ", mis. freq = " << format("%.1f", MisFrequency) << "%"; + BC.outs() << Targets[I].To.Addr; + BC.outs() << ", calls = " << Targets[I].Branches + << ", mispreds = " << Targets[I].Mispreds + << ", taken freq = " << format("%.1f", Frequency) << "%" + << ", mis. freq = " << format("%.1f", MisFrequency) << "%"; bool First = true; for (uint64_t JTIndex : Targets[I].JTIndices) { - outs() << (First ? ", indices = " : ", ") << JTIndex; + BC.outs() << (First ? ", indices = " : ", ") << JTIndex; First = false; } - outs() << "\n"; + BC.outs() << "\n"; } LLVM_DEBUG({ @@ -1137,9 +1140,9 @@ void IndirectCallPromotion::printCallsiteInfo( }); } -void IndirectCallPromotion::runOnFunctions(BinaryContext &BC) { +Error IndirectCallPromotion::runOnFunctions(BinaryContext &BC) { if (opts::ICP == ICP_NONE) - return; + return Error::success(); auto &BFs = BC.getBinaryFunctions(); @@ -1222,9 +1225,9 @@ void IndirectCallPromotion::runOnFunctions(BinaryContext &BC) { Functions.insert(std::get<2>(IC)); ++Num; } - outs() << "BOLT-INFO: ICP Total indirect calls = " << TotalIndirectCalls - << ", " << Num << " callsites cover " << opts::ICPTopCallsites - << "% of all indirect calls\n"; + BC.outs() << "BOLT-INFO: ICP Total indirect calls = " << TotalIndirectCalls + << ", " << Num << " callsites cover " << opts::ICPTopCallsites + << "% of all indirect calls\n"; } for (BinaryFunction *FuncPtr : Functions) { @@ -1301,11 +1304,11 @@ void IndirectCallPromotion::runOnFunctions(BinaryContext &BC) { Info.getLivenessAnalysis().getStateBefore(Inst); if (!State || (State && (*State)[BC.MIB->getFlagsReg()])) { if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: ICP failed in " << Function << " @ " - << InstIdx << " in " << BB->getName() - << ", calls = " << NumCalls - << (State ? ", cannot clobber flags reg.\n" - : ", no liveness data available.\n"); + BC.outs() << "BOLT-INFO: ICP failed in " << Function << " @ " + << InstIdx << " in " << BB->getName() + << ", calls = " << NumCalls + << (State ? ", cannot clobber flags reg.\n" + : ", no liveness data available.\n"); continue; } } @@ -1341,11 +1344,11 @@ void IndirectCallPromotion::runOnFunctions(BinaryContext &BC) { if (SymTargets.size() < N) { const size_t LastTarget = SymTargets.size(); if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: ICP failed in " << Function << " @ " - << InstIdx << " in " << BB->getName() - << ", calls = " << NumCalls - << ", ICP failed to find target symbol for " - << Targets[LastTarget].To.Sym->getName() << "\n"; + BC.outs() << "BOLT-INFO: ICP failed in " << Function << " @ " + << InstIdx << " in " << BB->getName() + << ", calls = " << NumCalls + << ", ICP failed to find target symbol for " + << Targets[LastTarget].To.Sym->getName() << "\n"; continue; } @@ -1374,10 +1377,10 @@ void IndirectCallPromotion::runOnFunctions(BinaryContext &BC) { if (ICPcode.empty()) { if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: ICP failed in " << Function << " @ " - << InstIdx << " in " << BB->getName() - << ", calls = " << NumCalls - << ", unable to generate promoted call code.\n"; + BC.outs() << "BOLT-INFO: ICP failed in " << Function << " @ " + << InstIdx << " in " << BB->getName() + << ", calls = " << NumCalls + << ", unable to generate promoted call code.\n"; continue; } @@ -1410,9 +1413,9 @@ void IndirectCallPromotion::runOnFunctions(BinaryContext &BC) { BBs.push_back(MergeBlock); if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: ICP succeeded in " << Function << " @ " - << InstIdx << " in " << BB->getName() - << " -> calls = " << NumCalls << "\n"; + BC.outs() << "BOLT-INFO: ICP succeeded in " << Function << " @ " + << InstIdx << " in " << BB->getName() + << " -> calls = " << NumCalls << "\n"; if (IsJumpTable) ++TotalOptimizedJumpTableCallsites; @@ -1426,52 +1429,54 @@ void IndirectCallPromotion::runOnFunctions(BinaryContext &BC) { TotalIndirectJmps += FuncTotalIndirectJmps; } - outs() << "BOLT-INFO: ICP total indirect callsites with profile = " - << TotalIndirectCallsites << "\n" - << "BOLT-INFO: ICP total jump table callsites = " - << TotalJumpTableCallsites << "\n" - << "BOLT-INFO: ICP total number of calls = " << TotalCalls << "\n" - << "BOLT-INFO: ICP percentage of calls that are indirect = " - << format("%.1f", (100.0 * TotalIndirectCalls) / TotalCalls) << "%\n" - << "BOLT-INFO: ICP percentage of indirect calls that can be " - "optimized = " - << format("%.1f", (100.0 * TotalNumFrequentCalls) / - std::max(TotalIndirectCalls, 1)) - << "%\n" - << "BOLT-INFO: ICP percentage of indirect callsites that are " - "optimized = " - << format("%.1f", (100.0 * TotalOptimizedIndirectCallsites) / - std::max(TotalIndirectCallsites, 1)) - << "%\n" - << "BOLT-INFO: ICP number of method load elimination candidates = " - << TotalMethodLoadEliminationCandidates << "\n" - << "BOLT-INFO: ICP percentage of method calls candidates that have " - "loads eliminated = " - << format("%.1f", (100.0 * TotalMethodLoadsEliminated) / - std::max( - TotalMethodLoadEliminationCandidates, 1)) - << "%\n" - << "BOLT-INFO: ICP percentage of indirect branches that are " - "optimized = " - << format("%.1f", (100.0 * TotalNumFrequentJmps) / - std::max(TotalIndirectJmps, 1)) - << "%\n" - << "BOLT-INFO: ICP percentage of jump table callsites that are " - << "optimized = " - << format("%.1f", (100.0 * TotalOptimizedJumpTableCallsites) / - std::max(TotalJumpTableCallsites, 1)) - << "%\n" - << "BOLT-INFO: ICP number of jump table callsites that can use hot " - << "indices = " << TotalIndexBasedCandidates << "\n" - << "BOLT-INFO: ICP percentage of jump table callsites that use hot " - "indices = " - << format("%.1f", (100.0 * TotalIndexBasedJumps) / - std::max(TotalIndexBasedCandidates, 1)) - << "%\n"; + BC.outs() + << "BOLT-INFO: ICP total indirect callsites with profile = " + << TotalIndirectCallsites << "\n" + << "BOLT-INFO: ICP total jump table callsites = " + << TotalJumpTableCallsites << "\n" + << "BOLT-INFO: ICP total number of calls = " << TotalCalls << "\n" + << "BOLT-INFO: ICP percentage of calls that are indirect = " + << format("%.1f", (100.0 * TotalIndirectCalls) / TotalCalls) << "%\n" + << "BOLT-INFO: ICP percentage of indirect calls that can be " + "optimized = " + << format("%.1f", (100.0 * TotalNumFrequentCalls) / + std::max(TotalIndirectCalls, 1)) + << "%\n" + << "BOLT-INFO: ICP percentage of indirect callsites that are " + "optimized = " + << format("%.1f", (100.0 * TotalOptimizedIndirectCallsites) / + std::max(TotalIndirectCallsites, 1)) + << "%\n" + << "BOLT-INFO: ICP number of method load elimination candidates = " + << TotalMethodLoadEliminationCandidates << "\n" + << "BOLT-INFO: ICP percentage of method calls candidates that have " + "loads eliminated = " + << format("%.1f", + (100.0 * TotalMethodLoadsEliminated) / + std::max(TotalMethodLoadEliminationCandidates, 1)) + << "%\n" + << "BOLT-INFO: ICP percentage of indirect branches that are " + "optimized = " + << format("%.1f", (100.0 * TotalNumFrequentJmps) / + std::max(TotalIndirectJmps, 1)) + << "%\n" + << "BOLT-INFO: ICP percentage of jump table callsites that are " + << "optimized = " + << format("%.1f", (100.0 * TotalOptimizedJumpTableCallsites) / + std::max(TotalJumpTableCallsites, 1)) + << "%\n" + << "BOLT-INFO: ICP number of jump table callsites that can use hot " + << "indices = " << TotalIndexBasedCandidates << "\n" + << "BOLT-INFO: ICP percentage of jump table callsites that use hot " + "indices = " + << format("%.1f", (100.0 * TotalIndexBasedJumps) / + std::max(TotalIndexBasedCandidates, 1)) + << "%\n"; #ifndef NDEBUG verifyProfile(BFs); #endif + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Passes/Inliner.cpp b/bolt/lib/Passes/Inliner.cpp index 8dcb8934f2d20f7974c03f67808a403f619fc40a..a3b2017aa32aa82dfc3dec7043bf2f9385d892d5 100644 --- a/bolt/lib/Passes/Inliner.cpp +++ b/bolt/lib/Passes/Inliner.cpp @@ -496,11 +496,11 @@ bool Inliner::inlineCallsInFunction(BinaryFunction &Function) { return DidInlining; } -void Inliner::runOnFunctions(BinaryContext &BC) { +Error Inliner::runOnFunctions(BinaryContext &BC) { opts::syncOptions(); if (!opts::inliningEnabled()) - return; + return Error::success(); bool InlinedOnce; unsigned NumIters = 0; @@ -540,10 +540,11 @@ void Inliner::runOnFunctions(BinaryContext &BC) { } while (InlinedOnce && NumIters < opts::InlineMaxIters); if (NumInlinedCallSites) - outs() << "BOLT-INFO: inlined " << NumInlinedDynamicCalls << " calls at " - << NumInlinedCallSites << " call sites in " << NumIters - << " iteration(s). Change in binary size: " << TotalInlinedBytes - << " bytes.\n"; + BC.outs() << "BOLT-INFO: inlined " << NumInlinedDynamicCalls << " calls at " + << NumInlinedCallSites << " call sites in " << NumIters + << " iteration(s). Change in binary size: " << TotalInlinedBytes + << " bytes.\n"; + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Passes/Instrumentation.cpp b/bolt/lib/Passes/Instrumentation.cpp index e54b0cacc4ca96c9d3ed1adb03fc478a6c567cf8..760ca84b4ef1c983a9c875e3b9f85896fe2ced9b 100644 --- a/bolt/lib/Passes/Instrumentation.cpp +++ b/bolt/lib/Passes/Instrumentation.cpp @@ -96,8 +96,8 @@ static bool hasAArch64ExclusiveMemop(BinaryFunction &Function) { for (const MCInst &Inst : BB) if (BC.MIB->isAArch64Exclusive(Inst)) { if (opts::Verbosity >= 1) - outs() << "BOLT-INSTRUMENTER: Function " << Function - << " has exclusive instructions, skip instrumentation\n"; + BC.outs() << "BOLT-INSTRUMENTER: Function " << Function + << " has exclusive instructions, skip instrumentation\n"; return true; } @@ -526,7 +526,7 @@ void Instrumentation::instrumentFunction(BinaryFunction &Function, FuncDesc->EdgesSet.clear(); } -void Instrumentation::runOnFunctions(BinaryContext &BC) { +Error Instrumentation::runOnFunctions(BinaryContext &BC) { const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/false, /*IsText=*/false, /*IsAllocatable=*/true); @@ -567,17 +567,16 @@ void Instrumentation::runOnFunctions(BinaryContext &BC) { ErrorOr SetupSection = BC.getUniqueSectionByName("I__setup"); - if (!SetupSection) { - llvm::errs() << "Cannot find I__setup section\n"; - exit(1); - } + if (!SetupSection) + return createFatalBOLTError("Cannot find I__setup section\n"); + MCSymbol *Target = BC.registerNameAtAddress( "__bolt_instr_setup", SetupSection->getAddress(), 0, 0); MCInst NewInst; BC.MIB->createCall(NewInst, Target, BC.Ctx.get()); BB.insertInstruction(BB.begin(), std::move(NewInst)); } else { - llvm::errs() << "BOLT-WARNING: Entry point not found\n"; + BC.errs() << "BOLT-WARNING: Entry point not found\n"; } if (BinaryData *BD = BC.getBinaryDataByName("___GLOBAL_init_65535/1")) { @@ -586,10 +585,9 @@ void Instrumentation::runOnFunctions(BinaryContext &BC) { BinaryBasicBlock &BB = Ctor->front(); ErrorOr FiniSection = BC.getUniqueSectionByName("I__fini"); - if (!FiniSection) { - llvm::errs() << "Cannot find I__fini section\n"; - exit(1); - } + if (!FiniSection) + return createFatalBOLTError("Cannot find I__fini section"); + MCSymbol *Target = BC.registerNameAtAddress( "__bolt_instr_fini", FiniSection->getAddress(), 0, 0); auto IsLEA = [&BC](const MCInst &Inst) { return BC.MIB->isLEA64r(Inst); }; @@ -598,11 +596,12 @@ void Instrumentation::runOnFunctions(BinaryContext &BC) { LEA->getOperand(4).setExpr( MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *BC.Ctx)); } else { - llvm::errs() << "BOLT-WARNING: ___GLOBAL_init_65535 not found\n"; + BC.errs() << "BOLT-WARNING: ___GLOBAL_init_65535 not found\n"; } } setupRuntimeLibrary(BC); + return Error::success(); } void Instrumentation::createAuxiliaryFunctions(BinaryContext &BC) { @@ -688,32 +687,34 @@ void Instrumentation::createAuxiliaryFunctions(BinaryContext &BC) { void Instrumentation::setupRuntimeLibrary(BinaryContext &BC) { uint32_t FuncDescSize = Summary->getFDSize(); - outs() << "BOLT-INSTRUMENTER: Number of indirect call site descriptors: " - << Summary->IndCallDescriptions.size() << "\n"; - outs() << "BOLT-INSTRUMENTER: Number of indirect call target descriptors: " - << Summary->IndCallTargetDescriptions.size() << "\n"; - outs() << "BOLT-INSTRUMENTER: Number of function descriptors: " - << Summary->FunctionDescriptions.size() << "\n"; - outs() << "BOLT-INSTRUMENTER: Number of branch counters: " << BranchCounters - << "\n"; - outs() << "BOLT-INSTRUMENTER: Number of ST leaf node counters: " - << LeafNodeCounters << "\n"; - outs() << "BOLT-INSTRUMENTER: Number of direct call counters: " - << DirectCallCounters << "\n"; - outs() << "BOLT-INSTRUMENTER: Total number of counters: " - << Summary->Counters.size() << "\n"; - outs() << "BOLT-INSTRUMENTER: Total size of counters: " - << (Summary->Counters.size() * 8) << " bytes (static alloc memory)\n"; - outs() << "BOLT-INSTRUMENTER: Total size of string table emitted: " - << Summary->StringTable.size() << " bytes in file\n"; - outs() << "BOLT-INSTRUMENTER: Total size of descriptors: " - << (FuncDescSize + - Summary->IndCallDescriptions.size() * sizeof(IndCallDescription) + - Summary->IndCallTargetDescriptions.size() * - sizeof(IndCallTargetDescription)) - << " bytes in file\n"; - outs() << "BOLT-INSTRUMENTER: Profile will be saved to file " - << opts::InstrumentationFilename << "\n"; + BC.outs() << "BOLT-INSTRUMENTER: Number of indirect call site descriptors: " + << Summary->IndCallDescriptions.size() << "\n"; + BC.outs() << "BOLT-INSTRUMENTER: Number of indirect call target descriptors: " + << Summary->IndCallTargetDescriptions.size() << "\n"; + BC.outs() << "BOLT-INSTRUMENTER: Number of function descriptors: " + << Summary->FunctionDescriptions.size() << "\n"; + BC.outs() << "BOLT-INSTRUMENTER: Number of branch counters: " + << BranchCounters << "\n"; + BC.outs() << "BOLT-INSTRUMENTER: Number of ST leaf node counters: " + << LeafNodeCounters << "\n"; + BC.outs() << "BOLT-INSTRUMENTER: Number of direct call counters: " + << DirectCallCounters << "\n"; + BC.outs() << "BOLT-INSTRUMENTER: Total number of counters: " + << Summary->Counters.size() << "\n"; + BC.outs() << "BOLT-INSTRUMENTER: Total size of counters: " + << (Summary->Counters.size() * 8) + << " bytes (static alloc memory)\n"; + BC.outs() << "BOLT-INSTRUMENTER: Total size of string table emitted: " + << Summary->StringTable.size() << " bytes in file\n"; + BC.outs() << "BOLT-INSTRUMENTER: Total size of descriptors: " + << (FuncDescSize + + Summary->IndCallDescriptions.size() * + sizeof(IndCallDescription) + + Summary->IndCallTargetDescriptions.size() * + sizeof(IndCallTargetDescription)) + << " bytes in file\n"; + BC.outs() << "BOLT-INSTRUMENTER: Profile will be saved to file " + << opts::InstrumentationFilename << "\n"; InstrumentationRuntimeLibrary *RtLibrary = static_cast(BC.getRuntimeLibrary()); diff --git a/bolt/lib/Passes/JTFootprintReduction.cpp b/bolt/lib/Passes/JTFootprintReduction.cpp index d690e4d0c003dd517783fe35c96ba8353f18d7cf..fd291f96004d93ccd076ed653ebb33aa0ab3b7c1 100644 --- a/bolt/lib/Passes/JTFootprintReduction.cpp +++ b/bolt/lib/Passes/JTFootprintReduction.cpp @@ -246,9 +246,9 @@ void JTFootprintReduction::optimizeFunction(BinaryFunction &Function, ++I; } -void JTFootprintReduction::runOnFunctions(BinaryContext &BC) { +Error JTFootprintReduction::runOnFunctions(BinaryContext &BC) { if (opts::JumpTables == JTS_BASIC && BC.HasRelocations) - return; + return Error::success(); std::unique_ptr RA; std::unique_ptr CG; @@ -272,23 +272,24 @@ void JTFootprintReduction::runOnFunctions(BinaryContext &BC) { } if (TotalJTs == TotalJTsDenied) { - outs() << "BOLT-INFO: JT Footprint reduction: no changes were made.\n"; - return; + BC.outs() << "BOLT-INFO: JT Footprint reduction: no changes were made.\n"; + return Error::success(); } - outs() << "BOLT-INFO: JT Footprint reduction stats (simple funcs only):\n"; + BC.outs() << "BOLT-INFO: JT Footprint reduction stats (simple funcs only):\n"; if (OptimizedScore) - outs() << format("\t %.2lf%%", (OptimizedScore * 100.0 / TotalJTScore)) - << " of dynamic JT entries were reduced.\n"; - outs() << "\t " << TotalJTs - TotalJTsDenied << " of " << TotalJTs - << " jump tables affected.\n"; - outs() << "\t " << IndJmps - IndJmpsDenied << " of " << IndJmps - << " indirect jumps to JTs affected.\n"; - outs() << "\t " << NumJTsBadMatch - << " JTs discarded due to unsupported jump pattern.\n"; - outs() << "\t " << NumJTsNoReg - << " JTs discarded due to register unavailability.\n"; - outs() << "\t " << BytesSaved << " bytes saved.\n"; + BC.outs() << format("\t %.2lf%%", (OptimizedScore * 100.0 / TotalJTScore)) + << " of dynamic JT entries were reduced.\n"; + BC.outs() << "\t " << TotalJTs - TotalJTsDenied << " of " << TotalJTs + << " jump tables affected.\n"; + BC.outs() << "\t " << IndJmps - IndJmpsDenied << " of " << IndJmps + << " indirect jumps to JTs affected.\n"; + BC.outs() << "\t " << NumJTsBadMatch + << " JTs discarded due to unsupported jump pattern.\n"; + BC.outs() << "\t " << NumJTsNoReg + << " JTs discarded due to register unavailability.\n"; + BC.outs() << "\t " << BytesSaved << " bytes saved.\n"; + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Passes/LongJmp.cpp b/bolt/lib/Passes/LongJmp.cpp index ded0db2cd30b611199c02a2263069d848402e43d..c483f70a836ee12f4e80eb228e6457087c442c8d 100644 --- a/bolt/lib/Passes/LongJmp.cpp +++ b/bolt/lib/Passes/LongJmp.cpp @@ -459,13 +459,13 @@ uint64_t LongJmpPass::getSymbolAddress(const BinaryContext &BC, return Iter->second; } -bool LongJmpPass::relaxStub(BinaryBasicBlock &StubBB) { +Error LongJmpPass::relaxStub(BinaryBasicBlock &StubBB, bool &Modified) { const BinaryFunction &Func = *StubBB.getFunction(); const BinaryContext &BC = Func.getBinaryContext(); const int Bits = StubBits[&StubBB]; // Already working with the largest range? if (Bits == static_cast(BC.AsmInfo->getCodePointerSize() * 8)) - return false; + return Error::success(); const static int RangeShortJmp = BC.MIB->getShortJmpEncodingSize(); const static int RangeSingleInstr = BC.MIB->getUncondBranchEncodingSize(); @@ -481,12 +481,12 @@ bool LongJmpPass::relaxStub(BinaryBasicBlock &StubBB) { : TgtAddress - DotAddress; // If it fits in one instruction, do not relax if (!(PCRelTgtAddress & SingleInstrMask)) - return false; + return Error::success(); // Fits short jmp if (!(PCRelTgtAddress & ShortJmpMask)) { if (Bits >= RangeShortJmp) - return false; + return Error::success(); LLVM_DEBUG(dbgs() << "Relaxing stub to short jump. PCRelTgtAddress = " << Twine::utohexstr(PCRelTgtAddress) @@ -494,22 +494,23 @@ bool LongJmpPass::relaxStub(BinaryBasicBlock &StubBB) { << "\n"); relaxStubToShortJmp(StubBB, RealTargetSym); StubBits[&StubBB] = RangeShortJmp; - return true; + Modified = true; + return Error::success(); } // The long jmp uses absolute address on AArch64 // So we could not use it for PIC binaries - if (BC.isAArch64() && !BC.HasFixedLoadAddress) { - errs() << "BOLT-ERROR: Unable to relax stub for PIC binary\n"; - exit(1); - } + if (BC.isAArch64() && !BC.HasFixedLoadAddress) + return createFatalBOLTError( + "BOLT-ERROR: Unable to relax stub for PIC binary\n"); LLVM_DEBUG(dbgs() << "Relaxing stub to long jump. PCRelTgtAddress = " << Twine::utohexstr(PCRelTgtAddress) << " RealTargetSym = " << RealTargetSym->getName() << "\n"); relaxStubToLongJmp(StubBB, RealTargetSym); StubBits[&StubBB] = static_cast(BC.AsmInfo->getCodePointerSize() * 8); - return true; + Modified = true; + return Error::success(); } bool LongJmpPass::needsStub(const BinaryBasicBlock &BB, const MCInst &Inst, @@ -539,9 +540,8 @@ bool LongJmpPass::needsStub(const BinaryBasicBlock &BB, const MCInst &Inst, return PCOffset < MinVal || PCOffset > MaxVal; } -bool LongJmpPass::relax(BinaryFunction &Func) { +Error LongJmpPass::relax(BinaryFunction &Func, bool &Modified) { const BinaryContext &BC = Func.getBinaryContext(); - bool Modified = false; assert(BC.isAArch64() && "Unsupported arch"); constexpr int InsnSize = 4; // AArch64 @@ -613,7 +613,8 @@ bool LongJmpPass::relax(BinaryFunction &Func) { if (!Stubs[&Func].count(&BB) || !BB.isValid()) continue; - Modified |= relaxStub(BB); + if (auto E = relaxStub(BB, Modified)) + return Error(std::move(E)); } for (std::pair> &Elmt : @@ -625,11 +626,11 @@ bool LongJmpPass::relax(BinaryFunction &Func) { Func.insertBasicBlocks(Elmt.first, std::move(NewBBs), true); } - return Modified; + return Error::success(); } -void LongJmpPass::runOnFunctions(BinaryContext &BC) { - outs() << "BOLT-INFO: Starting stub-insertion pass\n"; +Error LongJmpPass::runOnFunctions(BinaryContext &BC) { + BC.outs() << "BOLT-INFO: Starting stub-insertion pass\n"; std::vector Sorted = BC.getSortedFunctions(); bool Modified; uint32_t Iterations = 0; @@ -639,19 +640,19 @@ void LongJmpPass::runOnFunctions(BinaryContext &BC) { tentativeLayout(BC, Sorted); updateStubGroups(); for (BinaryFunction *Func : Sorted) { - if (relax(*Func)) { - // Don't ruin non-simple functions, they can't afford to have the layout - // changed. - if (Func->isSimple()) - Func->fixBranches(); - Modified = true; - } + if (auto E = relax(*Func, Modified)) + return Error(std::move(E)); + // Don't ruin non-simple functions, they can't afford to have the layout + // changed. + if (Modified && Func->isSimple()) + Func->fixBranches(); } } while (Modified); - outs() << "BOLT-INFO: Inserted " << NumHotStubs - << " stubs in the hot area and " << NumColdStubs - << " stubs in the cold area. Shared " << NumSharedStubs - << " times, iterated " << Iterations << " times.\n"; + BC.outs() << "BOLT-INFO: Inserted " << NumHotStubs + << " stubs in the hot area and " << NumColdStubs + << " stubs in the cold area. Shared " << NumSharedStubs + << " times, iterated " << Iterations << " times.\n"; + return Error::success(); } } // namespace bolt } // namespace llvm diff --git a/bolt/lib/Passes/LoopInversionPass.cpp b/bolt/lib/Passes/LoopInversionPass.cpp index f30e1a8f7450ff333b8b39f66c2f53dd13029c8a..250a971d204c0a9f3ee0c72b223771f52c7b81a0 100644 --- a/bolt/lib/Passes/LoopInversionPass.cpp +++ b/bolt/lib/Passes/LoopInversionPass.cpp @@ -84,11 +84,11 @@ bool LoopInversionPass::runOnFunction(BinaryFunction &BF) { return IsChanged; } -void LoopInversionPass::runOnFunctions(BinaryContext &BC) { +Error LoopInversionPass::runOnFunctions(BinaryContext &BC) { std::atomic ModifiedFuncCount{0}; if (opts::ReorderBlocks == ReorderBasicBlocks::LT_NONE || opts::LoopReorder == false) - return; + return Error::success(); ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) { if (runOnFunction(BF)) @@ -103,8 +103,9 @@ void LoopInversionPass::runOnFunctions(BinaryContext &BC) { BC, ParallelUtilities::SchedulingPolicy::SP_TRIVIAL, WorkFun, SkipFunc, "LoopInversionPass"); - outs() << "BOLT-INFO: " << ModifiedFuncCount - << " Functions were reordered by LoopInversionPass\n"; + BC.outs() << "BOLT-INFO: " << ModifiedFuncCount + << " Functions were reordered by LoopInversionPass\n"; + return Error::success(); } } // end namespace bolt diff --git a/bolt/lib/Passes/PLTCall.cpp b/bolt/lib/Passes/PLTCall.cpp index aec75be84bfa32e8fb77d064e8534643c29c8a17..d0276f22e14ef8b3561be63cc062b649a56c79b7 100644 --- a/bolt/lib/Passes/PLTCall.cpp +++ b/bolt/lib/Passes/PLTCall.cpp @@ -43,9 +43,9 @@ PLT("plt", namespace llvm { namespace bolt { -void PLTCall::runOnFunctions(BinaryContext &BC) { +Error PLTCall::runOnFunctions(BinaryContext &BC) { if (opts::PLT == OT_NONE) - return; + return Error::success(); uint64_t NumCallsOptimized = 0; for (auto &It : BC.getBinaryFunctions()) { @@ -80,9 +80,10 @@ void PLTCall::runOnFunctions(BinaryContext &BC) { if (NumCallsOptimized) { BC.RequiresZNow = true; - outs() << "BOLT-INFO: " << NumCallsOptimized - << " PLT calls in the binary were optimized.\n"; + BC.outs() << "BOLT-INFO: " << NumCallsOptimized + << " PLT calls in the binary were optimized.\n"; } + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Passes/PatchEntries.cpp b/bolt/lib/Passes/PatchEntries.cpp index ee7512d89962f69b477ffbfe69ed04264ead8e5a..981d1b70af90702b4b352ba09503e7f699264494 100644 --- a/bolt/lib/Passes/PatchEntries.cpp +++ b/bolt/lib/Passes/PatchEntries.cpp @@ -31,7 +31,7 @@ llvm::cl::opt namespace llvm { namespace bolt { -void PatchEntries::runOnFunctions(BinaryContext &BC) { +Error PatchEntries::runOnFunctions(BinaryContext &BC) { if (!opts::ForcePatch) { // Mark the binary for patching if we did not create external references // for original code in any of functions we are not going to emit. @@ -42,11 +42,11 @@ void PatchEntries::runOnFunctions(BinaryContext &BC) { }); if (!NeedsPatching) - return; + return Error::success(); } if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: patching entries in original code\n"; + BC.outs() << "BOLT-INFO: patching entries in original code\n"; // Calculate the size of the patch. static size_t PatchSize = 0; @@ -78,8 +78,8 @@ void PatchEntries::runOnFunctions(BinaryContext &BC) { const MCSymbol *Symbol) { if (Offset < NextValidByte) { if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: unable to patch entry point in " << Function - << " at offset 0x" << Twine::utohexstr(Offset) << '\n'; + BC.outs() << "BOLT-INFO: unable to patch entry point in " << Function + << " at offset 0x" << Twine::utohexstr(Offset) << '\n'; return false; } @@ -89,8 +89,8 @@ void PatchEntries::runOnFunctions(BinaryContext &BC) { NextValidByte = Offset + PatchSize; if (NextValidByte > Function.getMaxSize()) { if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: function " << Function - << " too small to patch its entry point\n"; + BC.outs() << "BOLT-INFO: function " << Function + << " too small to patch its entry point\n"; return false; } @@ -101,9 +101,9 @@ void PatchEntries::runOnFunctions(BinaryContext &BC) { // We can't change output layout for AArch64 due to LongJmp pass if (BC.isAArch64()) { if (opts::ForcePatch) { - errs() << "BOLT-ERROR: unable to patch entries in " << Function - << "\n"; - exit(1); + BC.errs() << "BOLT-ERROR: unable to patch entries in " << Function + << "\n"; + return createFatalBOLTError(""); } continue; @@ -111,8 +111,8 @@ void PatchEntries::runOnFunctions(BinaryContext &BC) { // If the original function entries cannot be patched, then we cannot // safely emit new function body. - errs() << "BOLT-WARNING: failed to patch entries in " << Function - << ". The function will not be optimized.\n"; + BC.errs() << "BOLT-WARNING: failed to patch entries in " << Function + << ". The function will not be optimized.\n"; Function.setIgnored(); continue; } @@ -138,6 +138,7 @@ void PatchEntries::runOnFunctions(BinaryContext &BC) { Function.setIsPatched(true); } + return Error::success(); } } // end namespace bolt diff --git a/bolt/lib/Passes/RegAnalysis.cpp b/bolt/lib/Passes/RegAnalysis.cpp index eab16cb0903289b9207daa0caddfb283a6722c71..9054385c20b59b943bb831c4d4a0a7ccb6283e0f 100644 --- a/bolt/lib/Passes/RegAnalysis.cpp +++ b/bolt/lib/Passes/RegAnalysis.cpp @@ -232,11 +232,11 @@ BitVector RegAnalysis::getFunctionClobberList(const BinaryFunction *Func) { } void RegAnalysis::printStats() { - outs() << "BOLT-INFO REG ANALYSIS: Number of functions conservatively " - "treated as clobbering all registers: " - << NumFunctionsAllClobber - << format(" (%.1lf%% dyn cov)\n", - (100.0 * CountFunctionsAllClobber / CountDenominator)); + BC.outs() << "BOLT-INFO REG ANALYSIS: Number of functions conservatively " + "treated as clobbering all registers: " + << NumFunctionsAllClobber + << format(" (%.1lf%% dyn cov)\n", + (100.0 * CountFunctionsAllClobber / CountDenominator)); } } // namespace bolt diff --git a/bolt/lib/Passes/RegReAssign.cpp b/bolt/lib/Passes/RegReAssign.cpp index 8b9dc9c1fdd506c89e9cb97b2ca1612687d6e407..0becfb4a06a38c842b3c6fc269000dcfa56e5209 100644 --- a/bolt/lib/Passes/RegReAssign.cpp +++ b/bolt/lib/Passes/RegReAssign.cpp @@ -452,7 +452,7 @@ void RegReAssign::setupConservativePass( }); } -void RegReAssign::runOnFunctions(BinaryContext &BC) { +Error RegReAssign::runOnFunctions(BinaryContext &BC) { RegScore = std::vector(BC.MRI->getNumRegs(), 0); RankedRegs = std::vector(BC.MRI->getNumRegs(), 0); @@ -480,18 +480,20 @@ void RegReAssign::runOnFunctions(BinaryContext &BC) { } if (FuncsChanged.empty()) { - outs() << "BOLT-INFO: Reg Reassignment Pass: no changes were made.\n"; - return; + BC.outs() << "BOLT-INFO: Reg Reassignment Pass: no changes were made.\n"; + return Error::success(); } if (opts::UpdateDebugSections) - outs() << "BOLT-WARNING: You used -reg-reassign and -update-debug-sections." - << " Some registers were changed but associated AT_LOCATION for " - << "impacted variables were NOT updated! This operation is " - << "currently unsupported by BOLT.\n"; - outs() << "BOLT-INFO: Reg Reassignment Pass Stats:\n"; - outs() << "\t " << FuncsChanged.size() << " functions affected.\n"; - outs() << "\t " << StaticBytesSaved << " static bytes saved.\n"; - outs() << "\t " << DynBytesSaved << " dynamic bytes saved.\n"; + BC.outs() + << "BOLT-WARNING: You used -reg-reassign and -update-debug-sections." + << " Some registers were changed but associated AT_LOCATION for " + << "impacted variables were NOT updated! This operation is " + << "currently unsupported by BOLT.\n"; + BC.outs() << "BOLT-INFO: Reg Reassignment Pass Stats:\n"; + BC.outs() << "\t " << FuncsChanged.size() << " functions affected.\n"; + BC.outs() << "\t " << StaticBytesSaved << " static bytes saved.\n"; + BC.outs() << "\t " << DynBytesSaved << " dynamic bytes saved.\n"; + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Passes/ReorderData.cpp b/bolt/lib/Passes/ReorderData.cpp index 3a6654cf1e0b560e0ed6063811a329d96d693a92..2b04361c9463fa0e4f2a464b147907e193a1678e 100644 --- a/bolt/lib/Passes/ReorderData.cpp +++ b/bolt/lib/Passes/ReorderData.cpp @@ -133,7 +133,7 @@ bool filterSymbol(const BinaryData *BD) { using DataOrder = ReorderData::DataOrder; -void ReorderData::printOrder(const BinarySection &Section, +void ReorderData::printOrder(BinaryContext &BC, const BinarySection &Section, DataOrder::const_iterator Begin, DataOrder::const_iterator End) const { uint64_t TotalSize = 0; @@ -142,19 +142,20 @@ void ReorderData::printOrder(const BinarySection &Section, const BinaryData *BD = Begin->first; if (!PrintHeader) { - outs() << "BOLT-INFO: Hot global symbols for " << Section.getName() - << ":\n"; + BC.outs() << "BOLT-INFO: Hot global symbols for " << Section.getName() + << ":\n"; PrintHeader = true; } - outs() << "BOLT-INFO: " << *BD << ", moveable=" << BD->isMoveable() - << format(", weight=%.5f\n", double(Begin->second) / BD->getSize()); + BC.outs() << "BOLT-INFO: " << *BD << ", moveable=" << BD->isMoveable() + << format(", weight=%.5f\n", + double(Begin->second) / BD->getSize()); TotalSize += BD->getSize(); ++Begin; } if (TotalSize) - outs() << "BOLT-INFO: Total hot symbol size = " << TotalSize << "\n"; + BC.outs() << "BOLT-INFO: Total hot symbol size = " << TotalSize << "\n"; } DataOrder ReorderData::baseOrder(BinaryContext &BC, @@ -208,19 +209,19 @@ void ReorderData::assignMemData(BinaryContext &BC) { } if (!Counts.empty()) { - outs() << "BOLT-INFO: Memory stats breakdown:\n"; + BC.outs() << "BOLT-INFO: Memory stats breakdown:\n"; for (const auto &KV : Counts) { StringRef Section = KV.first; const uint64_t Count = KV.second; - outs() << "BOLT-INFO: " << Section << " = " << Count - << format(" (%.1f%%)\n", 100.0 * Count / TotalCount); + BC.outs() << "BOLT-INFO: " << Section << " = " << Count + << format(" (%.1f%%)\n", 100.0 * Count / TotalCount); if (JumpTableCounts.count(Section) != 0) { const uint64_t JTCount = JumpTableCounts[Section]; - outs() << "BOLT-INFO: jump tables = " << JTCount - << format(" (%.1f%%)\n", 100.0 * JTCount / Count); + BC.outs() << "BOLT-INFO: jump tables = " << JTCount + << format(" (%.1f%%)\n", 100.0 * JTCount / Count); } } - outs() << "BOLT-INFO: Total memory events: " << TotalCount << "\n"; + BC.outs() << "BOLT-INFO: Total memory events: " << TotalCount << "\n"; } } @@ -395,9 +396,9 @@ void ReorderData::setSectionOrder(BinaryContext &BC, OutputSection.reorderContents(NewOrder, opts::ReorderInplace); - outs() << "BOLT-INFO: reorder-data: " << Count << "/" << TotalCount - << format(" (%.1f%%)", 100.0 * Count / TotalCount) << " events, " - << Offset << " hot bytes\n"; + BC.outs() << "BOLT-INFO: reorder-data: " << Count << "/" << TotalCount + << format(" (%.1f%%)", 100.0 * Count / TotalCount) << " events, " + << Offset << " hot bytes\n"; } bool ReorderData::markUnmoveableSymbols(BinaryContext &BC, @@ -435,17 +436,17 @@ bool ReorderData::markUnmoveableSymbols(BinaryContext &BC, return FoundUnmoveable; } -void ReorderData::runOnFunctions(BinaryContext &BC) { +Error ReorderData::runOnFunctions(BinaryContext &BC) { static const char *DefaultSections[] = {".rodata", ".data", ".bss", nullptr}; if (!BC.HasRelocations || opts::ReorderData.empty()) - return; + return Error::success(); // For now if (opts::JumpTables > JTS_BASIC) { - outs() << "BOLT-WARNING: jump table support must be basic for " - << "data reordering to work.\n"; - return; + BC.outs() << "BOLT-WARNING: jump table support must be basic for " + << "data reordering to work.\n"; + return Error::success(); } assignMemData(BC); @@ -463,14 +464,14 @@ void ReorderData::runOnFunctions(BinaryContext &BC) { ErrorOr Section = BC.getUniqueSectionByName(SectionName); if (!Section) { - outs() << "BOLT-WARNING: Section " << SectionName - << " not found, skipping.\n"; + BC.outs() << "BOLT-WARNING: Section " << SectionName + << " not found, skipping.\n"; continue; } if (!isSupported(*Section)) { - outs() << "BOLT-ERROR: Section " << SectionName << " not supported.\n"; - exit(1); + BC.errs() << "BOLT-ERROR: Section " << SectionName << " not supported.\n"; + return createFatalBOLTError(""); } Sections.push_back(&*Section); @@ -483,23 +484,23 @@ void ReorderData::runOnFunctions(BinaryContext &BC) { unsigned SplitPointIdx; if (opts::ReorderAlgorithm == opts::ReorderAlgo::REORDER_COUNT) { - outs() << "BOLT-INFO: reorder-sections: ordering data by count\n"; + BC.outs() << "BOLT-INFO: reorder-sections: ordering data by count\n"; std::tie(Order, SplitPointIdx) = sortedByCount(BC, *Section); } else { - outs() << "BOLT-INFO: reorder-sections: ordering data by funcs\n"; + BC.outs() << "BOLT-INFO: reorder-sections: ordering data by funcs\n"; std::tie(Order, SplitPointIdx) = sortedByFunc(BC, *Section, BC.getBinaryFunctions()); } auto SplitPoint = Order.begin() + SplitPointIdx; if (opts::PrintReorderedData) - printOrder(*Section, Order.begin(), SplitPoint); + printOrder(BC, *Section, Order.begin(), SplitPoint); if (!opts::ReorderInplace || FoundUnmoveable) { if (opts::ReorderInplace && FoundUnmoveable) - outs() << "BOLT-INFO: Found unmoveable symbols in " - << Section->getName() << " falling back to splitting " - << "instead of in-place reordering.\n"; + BC.outs() << "BOLT-INFO: Found unmoveable symbols in " + << Section->getName() << " falling back to splitting " + << "instead of in-place reordering.\n"; // Rename sections. BinarySection &Hot = @@ -519,10 +520,12 @@ void ReorderData::runOnFunctions(BinaryContext &BC) { } } } else { - outs() << "BOLT-WARNING: Inplace section reordering not supported yet.\n"; + BC.outs() + << "BOLT-WARNING: Inplace section reordering not supported yet.\n"; setSectionOrder(BC, *Section, Order.begin(), Order.end()); } } + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Passes/ReorderFunctions.cpp b/bolt/lib/Passes/ReorderFunctions.cpp index 2446524c1ab416c2f3bfcd49c6e5418be01fc1e7..c2d540135bdaa1f2f26d72f09423b973d87308a1 100644 --- a/bolt/lib/Passes/ReorderFunctions.cpp +++ b/bolt/lib/Passes/ReorderFunctions.cpp @@ -114,7 +114,8 @@ using NodeId = CallGraph::NodeId; using Arc = CallGraph::Arc; using Node = CallGraph::Node; -void ReorderFunctions::reorder(std::vector &&Clusters, +void ReorderFunctions::reorder(BinaryContext &BC, + std::vector &&Clusters, std::map &BFs) { std::vector FuncAddr(Cg.numNodes()); // Just for computing stats uint64_t TotalSize = 0; @@ -139,10 +140,11 @@ void ReorderFunctions::reorder(std::vector &&Clusters, if (opts::ReorderFunctions == RT_NONE) return; - printStats(Clusters, FuncAddr); + printStats(BC, Clusters, FuncAddr); } -void ReorderFunctions::printStats(const std::vector &Clusters, +void ReorderFunctions::printStats(BinaryContext &BC, + const std::vector &Clusters, const std::vector &FuncAddr) { if (opts::Verbosity == 0) { #ifndef NDEBUG @@ -167,11 +169,11 @@ void ReorderFunctions::printStats(const std::vector &Clusters, double TotalCalls4KB = 0; double TotalCalls2MB = 0; if (PrintDetailed) - outs() << "BOLT-INFO: Function reordering page layout\n" - << "BOLT-INFO: ============== page 0 ==============\n"; + BC.outs() << "BOLT-INFO: Function reordering page layout\n" + << "BOLT-INFO: ============== page 0 ==============\n"; for (const Cluster &Cluster : Clusters) { if (PrintDetailed) - outs() << format( + BC.outs() << format( "BOLT-INFO: -------- density = %.3lf (%u / %u) --------\n", Cluster.density(), Cluster.samples(), Cluster.size()); @@ -180,8 +182,8 @@ void ReorderFunctions::printStats(const std::vector &Clusters, Hotfuncs++; if (PrintDetailed) - outs() << "BOLT-INFO: hot func " << *Cg.nodeIdToFunc(FuncId) << " (" - << Cg.size(FuncId) << ")\n"; + BC.outs() << "BOLT-INFO: hot func " << *Cg.nodeIdToFunc(FuncId) + << " (" << Cg.size(FuncId) << ")\n"; uint64_t Dist = 0; uint64_t Calls = 0; @@ -193,12 +195,13 @@ void ReorderFunctions::printStats(const std::vector &Clusters, (FuncAddr[FuncId] + Arc.avgCallOffset())); const double W = Arc.weight(); if (D < 64 && PrintDetailed && opts::Verbosity > 2) - outs() << "BOLT-INFO: short (" << D << "B) call:\n" - << "BOLT-INFO: Src: " << *Cg.nodeIdToFunc(FuncId) << "\n" - << "BOLT-INFO: Dst: " << *Cg.nodeIdToFunc(Dst) << "\n" - << "BOLT-INFO: Weight = " << W << "\n" - << "BOLT-INFO: AvgOffset = " << Arc.avgCallOffset() - << "\n"; + BC.outs() << "BOLT-INFO: short (" << D << "B) call:\n" + << "BOLT-INFO: Src: " << *Cg.nodeIdToFunc(FuncId) + << "\n" + << "BOLT-INFO: Dst: " << *Cg.nodeIdToFunc(Dst) << "\n" + << "BOLT-INFO: Weight = " << W << "\n" + << "BOLT-INFO: AvgOffset = " << Arc.avgCallOffset() + << "\n"; Calls += W; if (D < 64) TotalCalls64B += W; @@ -208,63 +211,64 @@ void ReorderFunctions::printStats(const std::vector &Clusters, TotalCalls2MB += W; Dist += Arc.weight() * D; if (PrintDetailed) - outs() << format("BOLT-INFO: arc: %u [@%lu+%.1lf] -> %u [@%lu]: " - "weight = %.0lf, callDist = %f\n", - Arc.src(), FuncAddr[Arc.src()], - Arc.avgCallOffset(), Arc.dst(), - FuncAddr[Arc.dst()], Arc.weight(), D); + BC.outs() << format("BOLT-INFO: arc: %u [@%lu+%.1lf] -> %u [@%lu]: " + "weight = %.0lf, callDist = %f\n", + Arc.src(), FuncAddr[Arc.src()], + Arc.avgCallOffset(), Arc.dst(), + FuncAddr[Arc.dst()], Arc.weight(), D); } TotalCalls += Calls; TotalDistance += Dist; TotalSize += Cg.size(FuncId); if (PrintDetailed) { - outs() << format("BOLT-INFO: start = %6u : avgCallDist = %lu : ", - TotalSize, Calls ? Dist / Calls : 0) - << Cg.nodeIdToFunc(FuncId)->getPrintName() << '\n'; + BC.outs() << format("BOLT-INFO: start = %6u : avgCallDist = %lu : ", + TotalSize, Calls ? Dist / Calls : 0) + << Cg.nodeIdToFunc(FuncId)->getPrintName() << '\n'; const uint64_t NewPage = TotalSize / HugePageSize; if (NewPage != CurPage) { CurPage = NewPage; - outs() << format( + BC.outs() << format( "BOLT-INFO: ============== page %u ==============\n", CurPage); } } } } } - outs() << "BOLT-INFO: Function reordering stats\n" - << format("BOLT-INFO: Number of hot functions: %u\n" - "BOLT-INFO: Number of clusters: %lu\n", - Hotfuncs, Clusters.size()) - << format("BOLT-INFO: Final average call distance = %.1lf " - "(%.0lf / %.0lf)\n", - TotalCalls ? TotalDistance / TotalCalls : 0, TotalDistance, - TotalCalls) - << format("BOLT-INFO: Total Calls = %.0lf\n", TotalCalls); + BC.outs() << "BOLT-INFO: Function reordering stats\n" + << format("BOLT-INFO: Number of hot functions: %u\n" + "BOLT-INFO: Number of clusters: %lu\n", + Hotfuncs, Clusters.size()) + << format("BOLT-INFO: Final average call distance = %.1lf " + "(%.0lf / %.0lf)\n", + TotalCalls ? TotalDistance / TotalCalls : 0, + TotalDistance, TotalCalls) + << format("BOLT-INFO: Total Calls = %.0lf\n", TotalCalls); if (TotalCalls) - outs() << format("BOLT-INFO: Total Calls within 64B = %.0lf (%.2lf%%)\n", - TotalCalls64B, 100 * TotalCalls64B / TotalCalls) - << format("BOLT-INFO: Total Calls within 4KB = %.0lf (%.2lf%%)\n", - TotalCalls4KB, 100 * TotalCalls4KB / TotalCalls) - << format("BOLT-INFO: Total Calls within 2MB = %.0lf (%.2lf%%)\n", - TotalCalls2MB, 100 * TotalCalls2MB / TotalCalls); + BC.outs() + << format("BOLT-INFO: Total Calls within 64B = %.0lf (%.2lf%%)\n", + TotalCalls64B, 100 * TotalCalls64B / TotalCalls) + << format("BOLT-INFO: Total Calls within 4KB = %.0lf (%.2lf%%)\n", + TotalCalls4KB, 100 * TotalCalls4KB / TotalCalls) + << format("BOLT-INFO: Total Calls within 2MB = %.0lf (%.2lf%%)\n", + TotalCalls2MB, 100 * TotalCalls2MB / TotalCalls); } -std::vector ReorderFunctions::readFunctionOrderFile() { - std::vector FunctionNames; +Error ReorderFunctions::readFunctionOrderFile( + std::vector &FunctionNames) { std::ifstream FuncsFile(opts::FunctionOrderFile, std::ios::in); - if (!FuncsFile) { - errs() << "Ordered functions file \"" << opts::FunctionOrderFile - << "\" can't be opened.\n"; - exit(1); - } + if (!FuncsFile) + return createFatalBOLTError(Twine("Ordered functions file \"") + + Twine(opts::FunctionOrderFile) + + Twine("\" can't be opened.")); + std::string FuncName; while (std::getline(FuncsFile, FuncName)) FunctionNames.push_back(FuncName); - return FunctionNames; + return Error::success(); } -void ReorderFunctions::runOnFunctions(BinaryContext &BC) { +Error ReorderFunctions::runOnFunctions(BinaryContext &BC) { auto &BFs = BC.getBinaryFunctions(); if (opts::ReorderFunctions != RT_NONE && opts::ReorderFunctions != RT_EXEC_COUNT && @@ -373,7 +377,11 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) { uint32_t Index = 0; uint32_t InvalidEntries = 0; - for (const std::string &Function : readFunctionOrderFile()) { + std::vector FunctionNames; + if (Error E = readFunctionOrderFile(FunctionNames)) + return Error(std::move(E)); + + for (const std::string &Function : FunctionNames) { std::vector FuncAddrs; BinaryData *BD = BC.getBinaryDataByName(Function); @@ -399,8 +407,8 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) { if (FuncAddrs.empty()) { if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: Reorder functions: can't find function " - << "for " << Function << "\n"; + BC.errs() << "BOLT-WARNING: Reorder functions: can't find function " + << "for " << Function << "\n"; ++InvalidEntries; continue; } @@ -412,28 +420,28 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) { BinaryFunction *BF = BC.getFunctionForSymbol(FuncBD->getSymbol()); if (!BF) { if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: Reorder functions: can't find function " - << "for " << Function << "\n"; + BC.errs() << "BOLT-WARNING: Reorder functions: can't find function " + << "for " << Function << "\n"; ++InvalidEntries; break; } if (!BF->hasValidIndex()) BF->setIndex(Index++); else if (opts::Verbosity > 0) - errs() << "BOLT-WARNING: Duplicate reorder entry for " << Function - << "\n"; + BC.errs() << "BOLT-WARNING: Duplicate reorder entry for " << Function + << "\n"; } } if (InvalidEntries) - errs() << "BOLT-WARNING: Reorder functions: can't find functions for " - << InvalidEntries << " entries in -function-order list\n"; + BC.errs() << "BOLT-WARNING: Reorder functions: can't find functions for " + << InvalidEntries << " entries in -function-order list\n"; } break; default: llvm_unreachable("unexpected layout type"); } - reorder(std::move(Clusters), BFs); + reorder(BC, std::move(Clusters), BFs); BC.HasFinalizedFunctionOrder = true; @@ -442,9 +450,9 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) { FuncsFile = std::make_unique(opts::GenerateFunctionOrderFile, std::ios::out); if (!FuncsFile) { - errs() << "BOLT-ERROR: ordered functions file " - << opts::GenerateFunctionOrderFile << " cannot be opened\n"; - exit(1); + BC.errs() << "BOLT-ERROR: ordered functions file " + << opts::GenerateFunctionOrderFile << " cannot be opened\n"; + return createFatalBOLTError(""); } } @@ -453,9 +461,9 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) { LinkSectionsFile = std::make_unique(opts::LinkSectionsFile, std::ios::out); if (!LinkSectionsFile) { - errs() << "BOLT-ERROR: link sections file " << opts::LinkSectionsFile - << " cannot be opened\n"; - exit(1); + BC.errs() << "BOLT-ERROR: link sections file " << opts::LinkSectionsFile + << " cannot be opened\n"; + return createFatalBOLTError(""); } } @@ -505,16 +513,17 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) { if (FuncsFile) { FuncsFile->close(); - outs() << "BOLT-INFO: dumped function order to " - << opts::GenerateFunctionOrderFile << '\n'; + BC.outs() << "BOLT-INFO: dumped function order to " + << opts::GenerateFunctionOrderFile << '\n'; } if (LinkSectionsFile) { LinkSectionsFile->close(); - outs() << "BOLT-INFO: dumped linker section order to " - << opts::LinkSectionsFile << '\n'; + BC.outs() << "BOLT-INFO: dumped linker section order to " + << opts::LinkSectionsFile << '\n'; } } + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Passes/RetpolineInsertion.cpp b/bolt/lib/Passes/RetpolineInsertion.cpp index 97eedb882f550688975d11d0a0b0d4f59d725944..2808575cc6bb4a7e1028ca3ea0050672fba1bc40 100644 --- a/bolt/lib/Passes/RetpolineInsertion.cpp +++ b/bolt/lib/Passes/RetpolineInsertion.cpp @@ -271,9 +271,9 @@ IndirectBranchInfo::IndirectBranchInfo(MCInst &Inst, MCPlusBuilder &MIB) { } } -void RetpolineInsertion::runOnFunctions(BinaryContext &BC) { +Error RetpolineInsertion::runOnFunctions(BinaryContext &BC) { if (!opts::InsertRetpolines) - return; + return Error::success(); assert(BC.isX86() && "retpoline insertion not supported for target architecture"); @@ -327,10 +327,11 @@ void RetpolineInsertion::runOnFunctions(BinaryContext &BC) { } } } - outs() << "BOLT-INFO: The number of created retpoline functions is : " - << CreatedRetpolines.size() - << "\nBOLT-INFO: The number of retpolined branches is : " - << RetpolinedBranches << "\n"; + BC.outs() << "BOLT-INFO: The number of created retpoline functions is : " + << CreatedRetpolines.size() + << "\nBOLT-INFO: The number of retpolined branches is : " + << RetpolinedBranches << "\n"; + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Passes/ShrinkWrapping.cpp b/bolt/lib/Passes/ShrinkWrapping.cpp index d7b25c1279dc8b25b6aeebc97ebf34df69a0e496..9a1f9d72623a388a275f204a72a0a092cf962123 100644 --- a/bolt/lib/Passes/ShrinkWrapping.cpp +++ b/bolt/lib/Passes/ShrinkWrapping.cpp @@ -1646,9 +1646,9 @@ void ShrinkWrapping::rebuildCFIForSP() { ++I; } -MCInst ShrinkWrapping::createStackAccess(int SPVal, int FPVal, - const FrameIndexEntry &FIE, - bool CreatePushOrPop) { +Expected ShrinkWrapping::createStackAccess(int SPVal, int FPVal, + const FrameIndexEntry &FIE, + bool CreatePushOrPop) { MCInst NewInst; if (SPVal != StackPointerTracking::SUPERPOSITION && SPVal != StackPointerTracking::EMPTY) { @@ -1656,15 +1656,15 @@ MCInst ShrinkWrapping::createStackAccess(int SPVal, int FPVal, if (!BC.MIB->createRestoreFromStack(NewInst, BC.MIB->getStackPointer(), FIE.StackOffset - SPVal, FIE.RegOrImm, FIE.Size)) { - errs() << "createRestoreFromStack: not supported on this platform\n"; - abort(); + return createFatalBOLTError( + "createRestoreFromStack: not supported on this platform\n"); } } else { if (!BC.MIB->createSaveToStack(NewInst, BC.MIB->getStackPointer(), FIE.StackOffset - SPVal, FIE.RegOrImm, FIE.Size)) { - errs() << "createSaveToStack: not supported on this platform\n"; - abort(); + return createFatalBOLTError( + "createSaveToStack: not supported on this platform\n"); } } if (CreatePushOrPop) @@ -1678,15 +1678,15 @@ MCInst ShrinkWrapping::createStackAccess(int SPVal, int FPVal, if (!BC.MIB->createRestoreFromStack(NewInst, BC.MIB->getFramePointer(), FIE.StackOffset - FPVal, FIE.RegOrImm, FIE.Size)) { - errs() << "createRestoreFromStack: not supported on this platform\n"; - abort(); + return createFatalBOLTError( + "createRestoreFromStack: not supported on this platform\n"); } } else { if (!BC.MIB->createSaveToStack(NewInst, BC.MIB->getFramePointer(), FIE.StackOffset - FPVal, FIE.RegOrImm, FIE.Size)) { - errs() << "createSaveToStack: not supported on this platform\n"; - abort(); + return createFatalBOLTError( + "createSaveToStack: not supported on this platform\n"); } } return NewInst; @@ -1743,10 +1743,11 @@ BBIterTy ShrinkWrapping::insertCFIsForPushOrPop(BinaryBasicBlock &BB, return Pos; } -BBIterTy ShrinkWrapping::processInsertion(BBIterTy InsertionPoint, - BinaryBasicBlock *CurBB, - const WorklistItem &Item, - int64_t SPVal, int64_t FPVal) { +Expected ShrinkWrapping::processInsertion(BBIterTy InsertionPoint, + BinaryBasicBlock *CurBB, + const WorklistItem &Item, + int64_t SPVal, + int64_t FPVal) { // Trigger CFI reconstruction for this CSR if necessary - writing to // PushOffsetByReg/PopOffsetByReg *will* trigger CFI update if ((Item.FIEToInsert.IsStore && @@ -1772,9 +1773,12 @@ BBIterTy ShrinkWrapping::processInsertion(BBIterTy InsertionPoint, << " Is push = " << (Item.Action == WorklistItem::InsertPushOrPop) << "\n"; }); - MCInst NewInst = + Expected NewInstOrErr = createStackAccess(SPVal, FPVal, Item.FIEToInsert, Item.Action == WorklistItem::InsertPushOrPop); + if (auto E = NewInstOrErr.takeError()) + return Error(std::move(E)); + MCInst &NewInst = *NewInstOrErr; if (InsertionPoint != CurBB->end()) { LLVM_DEBUG({ dbgs() << "Adding before Inst: "; @@ -1791,7 +1795,7 @@ BBIterTy ShrinkWrapping::processInsertion(BBIterTy InsertionPoint, return CurBB->end(); } -BBIterTy ShrinkWrapping::processInsertionsList( +Expected ShrinkWrapping::processInsertionsList( BBIterTy InsertionPoint, BinaryBasicBlock *CurBB, std::vector &TodoList, int64_t SPVal, int64_t FPVal) { bool HasInsertions = llvm::any_of(TodoList, [&](WorklistItem &Item) { @@ -1840,8 +1844,11 @@ BBIterTy ShrinkWrapping::processInsertionsList( Item.Action == WorklistItem::ChangeToAdjustment) continue; - InsertionPoint = + auto InsertionPointOrErr = processInsertion(InsertionPoint, CurBB, Item, SPVal, FPVal); + if (auto E = InsertionPointOrErr.takeError()) + return Error(std::move(E)); + InsertionPoint = *InsertionPointOrErr; if (Item.Action == WorklistItem::InsertPushOrPop && Item.FIEToInsert.IsStore) SPVal -= Item.FIEToInsert.Size; @@ -1852,7 +1859,7 @@ BBIterTy ShrinkWrapping::processInsertionsList( return InsertionPoint; } -bool ShrinkWrapping::processInsertions() { +Expected ShrinkWrapping::processInsertions() { PredictiveStackPointerTracking PSPT(BF, Todo, Info, AllocatorId); PSPT.run(); @@ -1875,14 +1882,20 @@ bool ShrinkWrapping::processInsertions() { auto Iter = I; std::pair SPTState = *PSPT.getStateAt(Iter == BB.begin() ? (ProgramPoint)&BB : &*(--Iter)); - I = processInsertionsList(I, &BB, List, SPTState.first, SPTState.second); + auto IterOrErr = + processInsertionsList(I, &BB, List, SPTState.first, SPTState.second); + if (auto E = IterOrErr.takeError()) + return Error(std::move(E)); + I = *IterOrErr; } // Process insertions at the end of bb auto WRI = Todo.find(&BB); if (WRI != Todo.end()) { std::pair SPTState = *PSPT.getStateAt(*BB.rbegin()); - processInsertionsList(BB.end(), &BB, WRI->second, SPTState.first, - SPTState.second); + if (auto E = processInsertionsList(BB.end(), &BB, WRI->second, + SPTState.first, SPTState.second) + .takeError()) + return Error(std::move(E)); Changes = true; } } @@ -1945,7 +1958,7 @@ void ShrinkWrapping::rebuildCFI() { } } -bool ShrinkWrapping::perform(bool HotOnly) { +Expected ShrinkWrapping::perform(bool HotOnly) { HasDeletedOffsetCFIs = BitVector(BC.MRI->getNumRegs(), false); PushOffsetByReg = std::vector(BC.MRI->getNumRegs(), 0LL); PopOffsetByReg = std::vector(BC.MRI->getNumRegs(), 0LL); @@ -1998,7 +2011,11 @@ bool ShrinkWrapping::perform(bool HotOnly) { }); SLM.performChanges(); // Early exit if processInsertions doesn't detect any todo items - if (!processInsertions()) + auto ModifiedOrErr = processInsertions(); + if (auto E = ModifiedOrErr.takeError()) + return Error(std::move(E)); + const bool Modified = *ModifiedOrErr; + if (!Modified) return false; processDeletions(); if (foldIdenticalSplitEdges()) { @@ -2018,28 +2035,28 @@ bool ShrinkWrapping::perform(bool HotOnly) { return true; } -void ShrinkWrapping::printStats() { - outs() << "BOLT-INFO: Shrink wrapping moved " << SpillsMovedRegularMode - << " spills inserting load/stores and " << SpillsMovedPushPopMode - << " spills inserting push/pops\n"; +void ShrinkWrapping::printStats(BinaryContext &BC) { + BC.outs() << "BOLT-INFO: Shrink wrapping moved " << SpillsMovedRegularMode + << " spills inserting load/stores and " << SpillsMovedPushPopMode + << " spills inserting push/pops\n"; if (!InstrDynamicCount || !StoreDynamicCount) return; - outs() << "BOLT-INFO: Shrink wrapping reduced " << SpillsMovedDynamicCount - << " store executions (" - << format("%.1lf%%", - (100.0 * SpillsMovedDynamicCount / InstrDynamicCount)) - << " total instructions executed, " - << format("%.1lf%%", - (100.0 * SpillsMovedDynamicCount / StoreDynamicCount)) - << " store instructions)\n"; - outs() << "BOLT-INFO: Shrink wrapping failed at reducing " - << SpillsFailedDynamicCount << " store executions (" - << format("%.1lf%%", - (100.0 * SpillsFailedDynamicCount / InstrDynamicCount)) - << " total instructions executed, " - << format("%.1lf%%", - (100.0 * SpillsFailedDynamicCount / StoreDynamicCount)) - << " store instructions)\n"; + BC.outs() << "BOLT-INFO: Shrink wrapping reduced " << SpillsMovedDynamicCount + << " store executions (" + << format("%.1lf%%", + (100.0 * SpillsMovedDynamicCount / InstrDynamicCount)) + << " total instructions executed, " + << format("%.1lf%%", + (100.0 * SpillsMovedDynamicCount / StoreDynamicCount)) + << " store instructions)\n"; + BC.outs() << "BOLT-INFO: Shrink wrapping failed at reducing " + << SpillsFailedDynamicCount << " store executions (" + << format("%.1lf%%", + (100.0 * SpillsFailedDynamicCount / InstrDynamicCount)) + << " total instructions executed, " + << format("%.1lf%%", + (100.0 * SpillsFailedDynamicCount / StoreDynamicCount)) + << " store instructions)\n"; } // Operators necessary as a result of using MCAnnotation diff --git a/bolt/lib/Passes/SplitFunctions.cpp b/bolt/lib/Passes/SplitFunctions.cpp index 5de07597300483a72e6fbfb1acd8a5f0c9146fd8..cdbb2a15f667c6b7dc2a06674028e583bbb27aaf 100644 --- a/bolt/lib/Passes/SplitFunctions.cpp +++ b/bolt/lib/Passes/SplitFunctions.cpp @@ -712,15 +712,15 @@ bool SplitFunctions::shouldOptimize(const BinaryFunction &BF) const { return BinaryFunctionPass::shouldOptimize(BF); } -void SplitFunctions::runOnFunctions(BinaryContext &BC) { +Error SplitFunctions::runOnFunctions(BinaryContext &BC) { if (!opts::SplitFunctions) - return; + return Error::success(); // If split strategy is not CDSplit, then a second run of the pass is not // needed after function reordering. if (BC.HasFinalizedFunctionOrder && opts::SplitStrategy != SplitFunctionsStrategy::CDSplit) - return; + return Error::success(); std::unique_ptr Strategy; bool ForceSequential = false; @@ -766,10 +766,12 @@ void SplitFunctions::runOnFunctions(BinaryContext &BC) { "SplitFunctions", ForceSequential); if (SplitBytesHot + SplitBytesCold > 0) - outs() << "BOLT-INFO: splitting separates " << SplitBytesHot - << " hot bytes from " << SplitBytesCold << " cold bytes " - << format("(%.2lf%% of split functions is hot).\n", - 100.0 * SplitBytesHot / (SplitBytesHot + SplitBytesCold)); + BC.outs() << "BOLT-INFO: splitting separates " << SplitBytesHot + << " hot bytes from " << SplitBytesCold << " cold bytes " + << format("(%.2lf%% of split functions is hot).\n", + 100.0 * SplitBytesHot / + (SplitBytesHot + SplitBytesCold)); + return Error::success(); } void SplitFunctions::splitFunction(BinaryFunction &BF, SplitStrategy &S) { @@ -899,9 +901,9 @@ void SplitFunctions::splitFunction(BinaryFunction &BF, SplitStrategy &S) { if (alignTo(OriginalHotSize, opts::SplitAlignThreshold) <= alignTo(HotSize, opts::SplitAlignThreshold) + opts::SplitThreshold) { if (opts::Verbosity >= 2) { - outs() << "BOLT-INFO: Reversing splitting of function " - << formatv("{0}:\n {1:x}, {2:x} -> {3:x}\n", BF, HotSize, - ColdSize, OriginalHotSize); + BC.outs() << "BOLT-INFO: Reversing splitting of function " + << formatv("{0}:\n {1:x}, {2:x} -> {3:x}\n", BF, HotSize, + ColdSize, OriginalHotSize); } // Reverse the action of createEHTrampolines(). The trampolines will be diff --git a/bolt/lib/Passes/StokeInfo.cpp b/bolt/lib/Passes/StokeInfo.cpp index 419ba236e1342b02cbb6a4934ac04dc48e49a4da..499cac4217099cdc680ca383154920453d5d0f68 100644 --- a/bolt/lib/Passes/StokeInfo.cpp +++ b/bolt/lib/Passes/StokeInfo.cpp @@ -97,7 +97,8 @@ bool StokeInfo::checkFunction(BinaryFunction &BF, DataflowInfoManager &DInfo, if (!BF.isSimple() || BF.isMultiEntry() || BF.empty()) return false; - outs() << " STOKE-INFO: analyzing function " << Name << "\n"; + BF.getBinaryContext().outs() + << " STOKE-INFO: analyzing function " << Name << "\n"; FuncInfo.FuncName = Name; FuncInfo.Offset = BF.getFileOffset(); @@ -140,19 +141,19 @@ bool StokeInfo::checkFunction(BinaryFunction &BF, DataflowInfoManager &DInfo, LiveOutBV &= DefaultLiveOutMask; getRegNameFromBitVec(BF.getBinaryContext(), LiveOutBV, &FuncInfo.LiveOut); - outs() << " STOKE-INFO: end function \n"; + BF.getBinaryContext().outs() << " STOKE-INFO: end function \n"; return true; } -void StokeInfo::runOnFunctions(BinaryContext &BC) { - outs() << "STOKE-INFO: begin of stoke pass\n"; +Error StokeInfo::runOnFunctions(BinaryContext &BC) { + BC.outs() << "STOKE-INFO: begin of stoke pass\n"; std::ofstream Outfile; if (!opts::StokeOutputDataFilename.empty()) { Outfile.open(opts::StokeOutputDataFilename); } else { - errs() << "STOKE-INFO: output file is required\n"; - return; + BC.errs() << "STOKE-INFO: output file is required\n"; + return Error::success(); } // check some context meta data @@ -185,7 +186,8 @@ void StokeInfo::runOnFunctions(BinaryContext &BC) { FuncInfo.printData(Outfile); } - outs() << "STOKE-INFO: end of stoke pass\n"; + BC.outs() << "STOKE-INFO: end of stoke pass\n"; + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Passes/TailDuplication.cpp b/bolt/lib/Passes/TailDuplication.cpp index e63d4be1392f4d8ca5e59ad6aaef3c93e45ee788..2163e3a6a008362586fc484efb97cfad71a43b52 100644 --- a/bolt/lib/Passes/TailDuplication.cpp +++ b/bolt/lib/Passes/TailDuplication.cpp @@ -633,9 +633,9 @@ void TailDuplication::runOnFunction(BinaryFunction &Function) { ModifiedFunctions++; } -void TailDuplication::runOnFunctions(BinaryContext &BC) { +Error TailDuplication::runOnFunctions(BinaryContext &BC) { if (opts::TailDuplicationMode == TailDuplication::TD_NONE) - return; + return Error::success(); for (auto &It : BC.getBinaryFunctions()) { BinaryFunction &Function = It.second; @@ -644,23 +644,26 @@ void TailDuplication::runOnFunctions(BinaryContext &BC) { runOnFunction(Function); } - outs() << "BOLT-INFO: tail duplication" - << format(" modified %zu (%.2f%%) functions;", ModifiedFunctions, - 100.0 * ModifiedFunctions / BC.getBinaryFunctions().size()) - << format(" duplicated %zu blocks (%zu bytes) responsible for", - DuplicatedBlockCount, DuplicatedByteCount) - << format(" %zu dynamic executions (%.2f%% of all block executions)", - DuplicationsDynamicCount, - 100.0 * DuplicationsDynamicCount / AllDynamicCount) - << "\n"; + BC.outs() + << "BOLT-INFO: tail duplication" + << format(" modified %zu (%.2f%%) functions;", ModifiedFunctions, + 100.0 * ModifiedFunctions / BC.getBinaryFunctions().size()) + << format(" duplicated %zu blocks (%zu bytes) responsible for", + DuplicatedBlockCount, DuplicatedByteCount) + << format(" %zu dynamic executions (%.2f%% of all block executions)", + DuplicationsDynamicCount, + 100.0 * DuplicationsDynamicCount / AllDynamicCount) + << "\n"; if (opts::TailDuplicationConstCopyPropagation) { - outs() << "BOLT-INFO: tail duplication " - << format("applied %zu static and %zu dynamic propagation deletions", + BC.outs() << "BOLT-INFO: tail duplication " + << format( + "applied %zu static and %zu dynamic propagation deletions", StaticInstructionDeletionCount, DynamicInstructionDeletionCount) - << "\n"; + << "\n"; } + return Error::success(); } } // end namespace bolt diff --git a/bolt/lib/Passes/ThreeWayBranch.cpp b/bolt/lib/Passes/ThreeWayBranch.cpp index dc320d53fb688206a49927d4d2163bb534116f7a..c69eac5614b976898a4594a11d62d4984d872193 100644 --- a/bolt/lib/Passes/ThreeWayBranch.cpp +++ b/bolt/lib/Passes/ThreeWayBranch.cpp @@ -147,7 +147,7 @@ void ThreeWayBranch::runOnFunction(BinaryFunction &Function) { } } -void ThreeWayBranch::runOnFunctions(BinaryContext &BC) { +Error ThreeWayBranch::runOnFunctions(BinaryContext &BC) { for (auto &It : BC.getBinaryFunctions()) { BinaryFunction &Function = It.second; if (!shouldRunOnFunction(Function)) @@ -155,8 +155,9 @@ void ThreeWayBranch::runOnFunctions(BinaryContext &BC) { runOnFunction(Function); } - outs() << "BOLT-INFO: number of three way branches order changed: " - << BranchesAltered << "\n"; + BC.outs() << "BOLT-INFO: number of three way branches order changed: " + << BranchesAltered << "\n"; + return Error::success(); } } // end namespace bolt diff --git a/bolt/lib/Passes/ValidateInternalCalls.cpp b/bolt/lib/Passes/ValidateInternalCalls.cpp index 516f91acb5084417e4844cd4948e525f79cefaa0..54ae621159cfa3bcd1587d4a4a680eb53089c006 100644 --- a/bolt/lib/Passes/ValidateInternalCalls.cpp +++ b/bolt/lib/Passes/ValidateInternalCalls.cpp @@ -302,9 +302,9 @@ bool ValidateInternalCalls::analyzeFunction(BinaryFunction &Function) const { return true; } -void ValidateInternalCalls::runOnFunctions(BinaryContext &BC) { +Error ValidateInternalCalls::runOnFunctions(BinaryContext &BC) { if (!BC.isX86()) - return; + return Error::success(); // Look for functions that need validation. This should be pretty rare. std::set NeedsValidation; @@ -323,7 +323,7 @@ void ValidateInternalCalls::runOnFunctions(BinaryContext &BC) { // Skip validation for non-relocation mode if (!BC.HasRelocations) - return; + return Error::success(); // Since few functions need validation, we can work with our most expensive // algorithms here. Fix the CFG treating internal calls as unconditional @@ -339,13 +339,15 @@ void ValidateInternalCalls::runOnFunctions(BinaryContext &BC) { } if (!Invalid.empty()) { - errs() << "BOLT-WARNING: will skip the following function(s) as unsupported" - " internal calls were detected:\n"; + BC.errs() + << "BOLT-WARNING: will skip the following function(s) as unsupported" + " internal calls were detected:\n"; for (BinaryFunction *Function : Invalid) { - errs() << " " << *Function << "\n"; + BC.errs() << " " << *Function << "\n"; Function->setIgnored(); } } + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Passes/ValidateMemRefs.cpp b/bolt/lib/Passes/ValidateMemRefs.cpp index 3324776830d1771e0110c5690f5151aad37df2ec..f29a97c43f497c289edbadfef7a59461f90b9694 100644 --- a/bolt/lib/Passes/ValidateMemRefs.cpp +++ b/bolt/lib/Passes/ValidateMemRefs.cpp @@ -72,13 +72,13 @@ void ValidateMemRefs::runOnFunction(BinaryFunction &BF) { } } -void ValidateMemRefs::runOnFunctions(BinaryContext &BC) { +Error ValidateMemRefs::runOnFunctions(BinaryContext &BC) { if (!BC.isX86()) - return; + return Error::success(); // Skip validation if not moving JT if (opts::JumpTables == JTS_NONE || opts::JumpTables == JTS_BASIC) - return; + return Error::success(); ParallelUtilities::WorkFuncWithAllocTy ProcessFunction = [&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId) { @@ -94,10 +94,11 @@ void ValidateMemRefs::runOnFunctions(BinaryContext &BC) { LLVM_DEBUG(dbgs() << "BOLT-DEBUG: memrefs validation is concluded\n"); if (!ReplacedReferences) - return; + return Error::success(); - outs() << "BOLT-INFO: validate-mem-refs updated " << ReplacedReferences - << " object references\n"; + BC.outs() << "BOLT-INFO: validate-mem-refs updated " << ReplacedReferences + << " object references\n"; + return Error::success(); } } // namespace llvm::bolt diff --git a/bolt/lib/Passes/VeneerElimination.cpp b/bolt/lib/Passes/VeneerElimination.cpp index 929c7360b7ffafd36da4cc6561bc5448afa15e6d..0bec11128c7cea91b1a802e465476a2981be2bd7 100644 --- a/bolt/lib/Passes/VeneerElimination.cpp +++ b/bolt/lib/Passes/VeneerElimination.cpp @@ -29,9 +29,9 @@ static llvm::cl::opt namespace llvm { namespace bolt { -void VeneerElimination::runOnFunctions(BinaryContext &BC) { +Error VeneerElimination::runOnFunctions(BinaryContext &BC) { if (!opts::EliminateVeneers || !BC.isAArch64()) - return; + return Error::success(); std::map &BFs = BC.getBinaryFunctions(); std::unordered_map VeneerDestinations; @@ -51,8 +51,8 @@ void VeneerElimination::runOnFunctions(BinaryContext &BC) { VeneerDestinations[Symbol] = VeneerTargetSymbol; } - outs() << "BOLT-INFO: number of removed linker-inserted veneers: " - << VeneersCount << "\n"; + BC.outs() << "BOLT-INFO: number of removed linker-inserted veneers: " + << VeneersCount << "\n"; // Handle veneers to veneers in case they occur for (auto &Entry : VeneerDestinations) { @@ -79,8 +79,8 @@ void VeneerElimination::runOnFunctions(BinaryContext &BC) { VeneerCallers++; if (!BC.MIB->replaceBranchTarget( Instr, VeneerDestinations[TargetSymbol], BC.Ctx.get())) { - errs() << "BOLT-ERROR: updating veneer call destination failed\n"; - exit(1); + return createFatalBOLTError( + "BOLT-ERROR: updating veneer call destination failed\n"); } } } @@ -90,6 +90,7 @@ void VeneerElimination::runOnFunctions(BinaryContext &BC) { dbgs() << "BOLT-INFO: number of linker-inserted veneers call sites: " << VeneerCallers << "\n"); (void)VeneerCallers; + return Error::success(); } } // namespace bolt diff --git a/bolt/lib/Profile/BoltAddressTranslation.cpp b/bolt/lib/Profile/BoltAddressTranslation.cpp index 6901e482ddfd4e87e97ead08706897aae9481848..8e18b21f696a6f17bced0c1c735469d7ff753b49 100644 --- a/bolt/lib/Profile/BoltAddressTranslation.cpp +++ b/bolt/lib/Profile/BoltAddressTranslation.cpp @@ -108,7 +108,7 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) { writeMaps(Maps, PrevAddress, OS); writeMaps(Maps, PrevAddress, OS); - outs() << "BOLT-INFO: Wrote " << Maps.size() << " BAT maps\n"; + BC.outs() << "BOLT-INFO: Wrote " << Maps.size() << " BAT maps\n"; } APInt BoltAddressTranslation::calculateBranchEntriesBitMask(MapTy &Map, @@ -201,7 +201,7 @@ void BoltAddressTranslation::writeMaps(std::map &Maps, } } -std::error_code BoltAddressTranslation::parse(StringRef Buf) { +std::error_code BoltAddressTranslation::parse(raw_ostream &OS, StringRef Buf) { DataExtractor DE = DataExtractor(Buf, true, 8); uint64_t Offset = 0; if (Buf.size() < 12) @@ -225,7 +225,7 @@ std::error_code BoltAddressTranslation::parse(StringRef Buf) { uint64_t PrevAddress = 0; parseMaps(HotFuncs, PrevAddress, DE, Offset, Err); parseMaps(HotFuncs, PrevAddress, DE, Offset, Err); - outs() << "BOLT-INFO: Parsed " << Maps.size() << " BAT entries\n"; + OS << "BOLT-INFO: Parsed " << Maps.size() << " BAT entries\n"; return errorToErrorCode(std::move(Err)); } diff --git a/bolt/lib/Rewrite/BinaryPassManager.cpp b/bolt/lib/Rewrite/BinaryPassManager.cpp index 9946608c96d8ee99b2ca7c977ca7999c3373d98d..489b33fe1c7c201aa11b07f76d5d369170b9ef02 100644 --- a/bolt/lib/Rewrite/BinaryPassManager.cpp +++ b/bolt/lib/Rewrite/BinaryPassManager.cpp @@ -268,7 +268,7 @@ const char BinaryFunctionPassManager::TimerGroupName[] = "passman"; const char BinaryFunctionPassManager::TimerGroupDesc[] = "Binary Function Pass Manager"; -void BinaryFunctionPassManager::runPasses() { +Error BinaryFunctionPassManager::runPasses() { auto &BFs = BC.getBinaryFunctions(); for (size_t PassIdx = 0; PassIdx < Passes.size(); PassIdx++) { const std::pair> @@ -281,13 +281,20 @@ void BinaryFunctionPassManager::runPasses() { formatv("{0:2}_{1}", PassIdx, Pass->getName()).str(); if (opts::Verbosity > 0) - outs() << "BOLT-INFO: Starting pass: " << Pass->getName() << "\n"; + BC.outs() << "BOLT-INFO: Starting pass: " << Pass->getName() << "\n"; NamedRegionTimer T(Pass->getName(), Pass->getName(), TimerGroupName, TimerGroupDesc, TimeOpts); - callWithDynoStats([this, &Pass] { Pass->runOnFunctions(BC); }, BFs, - Pass->getName(), opts::DynoStatsAll, BC.isAArch64()); + Error E = Error::success(); + callWithDynoStats( + BC.outs(), + [this, &E, &Pass] { + E = joinErrors(std::move(E), Pass->runOnFunctions(BC)); + }, + BFs, Pass->getName(), opts::DynoStatsAll, BC.isAArch64()); + if (E) + return Error(std::move(E)); if (opts::VerifyCFG && !std::accumulate( @@ -296,13 +303,13 @@ void BinaryFunctionPassManager::runPasses() { const std::pair &It) { return Valid && It.second.validateCFG(); })) { - errs() << "BOLT-ERROR: Invalid CFG detected after pass " - << Pass->getName() << "\n"; - exit(1); + return createFatalBOLTError( + Twine("BOLT-ERROR: Invalid CFG detected after pass ") + + Twine(Pass->getName()) + Twine("\n")); } if (opts::Verbosity > 0) - outs() << "BOLT-INFO: Finished pass: " << Pass->getName() << "\n"; + BC.outs() << "BOLT-INFO: Finished pass: " << Pass->getName() << "\n"; if (!opts::PrintAll && !opts::DumpDotAll && !Pass->printPass()) continue; @@ -315,15 +322,16 @@ void BinaryFunctionPassManager::runPasses() { if (!Pass->shouldPrint(Function)) continue; - Function.print(outs(), Message); + Function.print(BC.outs(), Message); if (opts::DumpDotAll) Function.dumpGraphForPass(PassIdName); } } + return Error::success(); } -void BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) { +Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) { BinaryFunctionPassManager Manager(BC); const DynoStats InitialDynoStats = @@ -516,7 +524,7 @@ void BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) { // in parallel and restore them Manager.registerPass(std::make_unique(NeverPrint)); - Manager.runPasses(); + return Manager.runPasses(); } } // namespace bolt diff --git a/bolt/lib/Rewrite/BoltDiff.cpp b/bolt/lib/Rewrite/BoltDiff.cpp index 16a90510962e8ee1855500b5201e0e195fe0dde6..fa43b7a2f92c23d04270bb13930faea443e91add 100644 --- a/bolt/lib/Rewrite/BoltDiff.cpp +++ b/bolt/lib/Rewrite/BoltDiff.cpp @@ -294,9 +294,9 @@ class RewriteInstanceDiff { } PrintProgramStats PPS(opts::NeverPrint); outs() << "* BOLT-DIFF: Starting print program stats pass for binary 1\n"; - PPS.runOnFunctions(*RI1.BC); + RI1.BC->logBOLTErrorsAndQuitOnFatal(PPS.runOnFunctions(*RI1.BC)); outs() << "* BOLT-DIFF: Starting print program stats pass for binary 2\n"; - PPS.runOnFunctions(*RI2.BC); + RI1.BC->logBOLTErrorsAndQuitOnFatal(PPS.runOnFunctions(*RI2.BC)); outs() << "=====\n"; outs() << "Inputs share " << BothHaveProfile << " functions with valid profile.\n"; @@ -700,9 +700,9 @@ void RewriteInstance::compare(RewriteInstance &RI2) { if (opts::ICF) { IdenticalCodeFolding ICF(opts::NeverPrint); outs() << "BOLT-DIFF: Starting ICF pass for binary 1"; - ICF.runOnFunctions(*BC); + BC->logBOLTErrorsAndQuitOnFatal(ICF.runOnFunctions(*BC)); outs() << "BOLT-DIFF: Starting ICF pass for binary 2"; - ICF.runOnFunctions(*RI2.BC); + BC->logBOLTErrorsAndQuitOnFatal(ICF.runOnFunctions(*RI2.BC)); } RewriteInstanceDiff RID(*this, RI2); diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp index cefccbdfa2f0126b0bcf0306c628e8e788dbc565..27fa937c7508c32629c69d67c71e16b723934e52 100644 --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -709,7 +709,7 @@ void DWARFRewriter::updateDebugInfo() { : LegacyRangesSectionWriter.get(); // Skipping CUs that failed to load. if (SplitCU) { - DIEBuilder DWODIEBuilder(&(*SplitCU)->getContext(), true); + DIEBuilder DWODIEBuilder(BC, &(*SplitCU)->getContext(), true); DWODIEBuilder.buildDWOUnit(**SplitCU); std::string DWOName = updateDWONameCompDir( *Unit, *DIEBlder, *DIEBlder->getUnitDIEbyUnit(*Unit)); @@ -754,7 +754,7 @@ void DWARFRewriter::updateDebugInfo() { AddrWriter->update(*DIEBlder, *Unit); }; - DIEBuilder DIEBlder(BC.DwCtx.get()); + DIEBuilder DIEBlder(BC, BC.DwCtx.get()); DIEBlder.buildTypeUnits(StrOffstsWriter.get()); SmallVector OutBuffer; std::unique_ptr ObjOS = @@ -1655,7 +1655,8 @@ createDwarfOnlyBC(const object::ObjectFile &File) { &File, false, DWARFContext::create(File, DWARFContext::ProcessDebugRelocations::Ignore, nullptr, "", WithColor::defaultErrorHandler, - WithColor::defaultWarningHandler))); + WithColor::defaultWarningHandler), + {llvm::outs(), llvm::errs()})); } StringMap diff --git a/bolt/lib/Rewrite/MachORewriteInstance.cpp b/bolt/lib/Rewrite/MachORewriteInstance.cpp index 8be8257f15c1ce9effcb19fad54cd077ea71a438..0970a0507ebe8803e6ae85789b8ec10618465211 100644 --- a/bolt/lib/Rewrite/MachORewriteInstance.cpp +++ b/bolt/lib/Rewrite/MachORewriteInstance.cpp @@ -103,7 +103,8 @@ MachORewriteInstance::MachORewriteInstance(object::MachOObjectFile *InputFile, : InputFile(InputFile), ToolPath(ToolPath) { ErrorAsOutParameter EAO(&Err); auto BCOrErr = BinaryContext::createBinaryContext( - InputFile, /* IsPIC */ true, DWARFContext::create(*InputFile)); + InputFile, /* IsPIC */ true, DWARFContext::create(*InputFile), + {llvm::outs(), llvm::errs()}); if (Error E = BCOrErr.takeError()) { Err = std::move(E); return; @@ -337,7 +338,7 @@ void MachORewriteInstance::disassembleFunctions() { BinaryFunction &Function = BFI.second; if (!Function.isSimple()) continue; - Function.disassemble(); + BC->logBOLTErrorsAndQuitOnFatal(Function.disassemble()); if (opts::PrintDisasm) Function.print(outs(), "after disassembly"); } @@ -348,10 +349,7 @@ void MachORewriteInstance::buildFunctionsCFG() { BinaryFunction &Function = BFI.second; if (!Function.isSimple()) continue; - if (!Function.buildCFG(/*AllocId*/ 0)) { - errs() << "BOLT-WARNING: failed to build CFG for the function " - << Function << "\n"; - } + BC->logBOLTErrorsAndQuitOnFatal(Function.buildCFG(/*AllocId*/ 0)); } } @@ -387,7 +385,7 @@ void MachORewriteInstance::runOptimizationPasses() { Manager.registerPass( std::make_unique(opts::PrintFinalized)); - Manager.runPasses(); + BC->logBOLTErrorsAndQuitOnFatal(Manager.runPasses()); } void MachORewriteInstance::mapInstrumentationSection( diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 9a242d94dd773302931ee56344ac2c2bfdca46c7..89ca13c427dcf912045758b004885e8ee7b25d68 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -309,9 +309,11 @@ bool refersToReorderedSection(ErrorOr Section) { Expected> RewriteInstance::create(ELFObjectFileBase *File, const int Argc, - const char *const *Argv, StringRef ToolPath) { + const char *const *Argv, StringRef ToolPath, + raw_ostream &Stdout, raw_ostream &Stderr) { Error Err = Error::success(); - auto RI = std::make_unique(File, Argc, Argv, ToolPath, Err); + auto RI = std::make_unique(File, Argc, Argv, ToolPath, + Stdout, Stderr, Err); if (Err) return std::move(Err); return std::move(RI); @@ -319,6 +321,7 @@ RewriteInstance::create(ELFObjectFileBase *File, const int Argc, RewriteInstance::RewriteInstance(ELFObjectFileBase *File, const int Argc, const char *const *Argv, StringRef ToolPath, + raw_ostream &Stdout, raw_ostream &Stderr, Error &Err) : InputFile(File), Argc(Argc), Argv(Argv), ToolPath(ToolPath), SHStrTab(StringTableBuilder::ELF) { @@ -333,17 +336,23 @@ RewriteInstance::RewriteInstance(ELFObjectFileBase *File, const int Argc, bool IsPIC = false; const ELFFile &Obj = ELF64LEFile->getELFFile(); if (Obj.getHeader().e_type != ELF::ET_EXEC) { - outs() << "BOLT-INFO: shared object or position-independent executable " + Stdout << "BOLT-INFO: shared object or position-independent executable " "detected\n"; IsPIC = true; } + // Make sure we don't miss any output on core dumps. + Stdout.SetUnbuffered(); + Stderr.SetUnbuffered(); + LLVM_DEBUG(dbgs().SetUnbuffered()); + auto BCOrErr = BinaryContext::createBinaryContext( File, IsPIC, DWARFContext::create(*File, DWARFContext::ProcessDebugRelocations::Ignore, nullptr, opts::DWPPathName, WithColor::defaultErrorHandler, - WithColor::defaultWarningHandler)); + WithColor::defaultWarningHandler), + JournalingStreams{Stdout, Stderr}); if (Error E = BCOrErr.takeError()) { Err = std::move(E); return; @@ -457,22 +466,23 @@ void RewriteInstance::markGnuRelroSections() { bool VMAContains = checkVMA(Phdr, *Sec, VMAOverlap); if (ImageOverlap) { if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: GNU_RELRO segment has partial file offset " - << "overlap with section " << BinarySection->getName() << '\n'; + BC->errs() << "BOLT-WARNING: GNU_RELRO segment has partial file offset " + << "overlap with section " << BinarySection->getName() + << '\n'; return; } if (VMAOverlap) { if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: GNU_RELRO segment has partial VMA overlap " - << "with section " << BinarySection->getName() << '\n'; + BC->errs() << "BOLT-WARNING: GNU_RELRO segment has partial VMA overlap " + << "with section " << BinarySection->getName() << '\n'; return; } if (!ImageContains || !VMAContains) return; BinarySection->setRelro(); if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: marking " << BinarySection->getName() - << " as GNU_RELRO\n"; + BC->outs() << "BOLT-INFO: marking " << BinarySection->getName() + << " as GNU_RELRO\n"; }; for (const ELFT::Phdr &Phdr : cantFail(Obj.program_headers())) @@ -523,7 +533,7 @@ Error RewriteInstance::discoverStorage() { } if (BC->IsLinuxKernel) - outs() << "BOLT-INFO: Linux kernel binary detected\n"; + BC->outs() << "BOLT-INFO: Linux kernel binary detected\n"; for (const SectionRef &Section : InputFile->sections()) { Expected SectionNameOrErr = Section.getName(); @@ -555,8 +565,8 @@ Error RewriteInstance::discoverStorage() { return createStringError(errc::executable_format_error, "no PT_LOAD pheader seen"); - outs() << "BOLT-INFO: first alloc address is 0x" - << Twine::utohexstr(BC->FirstAllocAddress) << '\n'; + BC->outs() << "BOLT-INFO: first alloc address is 0x" + << Twine::utohexstr(BC->FirstAllocAddress) << '\n'; FirstNonAllocatableOffset = NextAvailableOffset; @@ -588,9 +598,9 @@ Error RewriteInstance::discoverStorage() { NextAvailableAddress - BC->FirstAllocAddress && "PHDR table address calculation error"); - outs() << "BOLT-INFO: creating new program header table at address 0x" - << Twine::utohexstr(NextAvailableAddress) << ", offset 0x" - << Twine::utohexstr(NextAvailableOffset) << '\n'; + BC->outs() << "BOLT-INFO: creating new program header table at address 0x" + << Twine::utohexstr(NextAvailableAddress) << ", offset 0x" + << Twine::utohexstr(NextAvailableOffset) << '\n'; PHDRTableAddress = NextAvailableAddress; PHDRTableOffset = NextAvailableOffset; @@ -685,7 +695,8 @@ void RewriteInstance::patchBuildID() { uint64_t FileOffset = getFileOffsetForAddress(BuildIDSection->getAddress()); if (!FileOffset) { - errs() << "BOLT-WARNING: Non-allocatable build-id will not be updated.\n"; + BC->errs() + << "BOLT-WARNING: Non-allocatable build-id will not be updated.\n"; return; } @@ -693,17 +704,17 @@ void RewriteInstance::patchBuildID() { LastIDByte ^= 1; OS.pwrite(&LastIDByte, 1, FileOffset + IDOffset + BuildID.size() - 1); - outs() << "BOLT-INFO: patched build-id (flipped last bit)\n"; + BC->outs() << "BOLT-INFO: patched build-id (flipped last bit)\n"; } Error RewriteInstance::run() { assert(BC && "failed to create a binary context"); - outs() << "BOLT-INFO: Target architecture: " - << Triple::getArchTypeName( - (llvm::Triple::ArchType)InputFile->getArch()) - << "\n"; - outs() << "BOLT-INFO: BOLT version: " << BoltRevision << "\n"; + BC->outs() << "BOLT-INFO: Target architecture: " + << Triple::getArchTypeName( + (llvm::Triple::ArchType)InputFile->getArch()) + << "\n"; + BC->outs() << "BOLT-INFO: BOLT version: " << BoltRevision << "\n"; if (Error E = discoverStorage()) return E; @@ -758,10 +769,10 @@ Error RewriteInstance::run() { updateRtFiniReloc(); if (opts::OutputFilename == "/dev/null") { - outs() << "BOLT-INFO: skipping writing final binary to disk\n"; + BC->outs() << "BOLT-INFO: skipping writing final binary to disk\n"; return Error::success(); } else if (BC->IsLinuxKernel) { - errs() << "BOLT-WARNING: Linux kernel support is experimental\n"; + BC->errs() << "BOLT-WARNING: Linux kernel support is experimental\n"; } // Rewrite allocatable contents and copy non-allocatable parts with mods. @@ -786,13 +797,15 @@ void RewriteInstance::discoverFileObjects() { for (const ELFSymbolRef &Symbol : InputFile->symbols()) { Expected NameOrError = Symbol.getName(); if (NameOrError && NameOrError->starts_with("__asan_init")) { - errs() << "BOLT-ERROR: input file was compiled or linked with sanitizer " - "support. Cannot optimize.\n"; + BC->errs() + << "BOLT-ERROR: input file was compiled or linked with sanitizer " + "support. Cannot optimize.\n"; exit(1); } if (NameOrError && NameOrError->starts_with("__llvm_coverage_mapping")) { - errs() << "BOLT-ERROR: input file was compiled or linked with coverage " - "support. Cannot optimize.\n"; + BC->errs() + << "BOLT-ERROR: input file was compiled or linked with coverage " + "support. Cannot optimize.\n"; exit(1); } @@ -924,7 +937,7 @@ void RewriteInstance::discoverFileObjects() { StringRef SymName = cantFail(Symbol.getName(), "cannot get symbol name"); if (SymbolAddress == 0) { if (opts::Verbosity >= 1 && SymbolType == SymbolRef::ST_Function) - errs() << "BOLT-WARNING: function with 0 address seen\n"; + BC->errs() << "BOLT-WARNING: function with 0 address seen\n"; continue; } @@ -965,13 +978,13 @@ void RewriteInstance::discoverFileObjects() { if (BD->getSize() == ELFSymbolRef(Symbol).getSize() && BD->getAddress() == SymbolAddress) { if (opts::Verbosity > 1) - errs() << "BOLT-WARNING: ignoring duplicate global symbol " << Name - << "\n"; + BC->errs() << "BOLT-WARNING: ignoring duplicate global symbol " + << Name << "\n"; // Ignore duplicate entry - possibly a bug in the linker continue; } - errs() << "BOLT-ERROR: bad input binary, global symbol \"" << Name - << "\" is not unique\n"; + BC->errs() << "BOLT-ERROR: bad input binary, global symbol \"" << Name + << "\" is not unique\n"; exit(1); } UniqueName = Name; @@ -1059,9 +1072,9 @@ void RewriteInstance::discoverFileObjects() { !SymbolSize) { LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ignoring symbol as a marker\n"); } else if (opts::Verbosity > 1) { - errs() << "BOLT-WARNING: symbol " << UniqueName - << " seen in the middle of function " << *PreviousFunction - << ". Could be a new entry.\n"; + BC->errs() << "BOLT-WARNING: symbol " << UniqueName + << " seen in the middle of function " << *PreviousFunction + << ". Could be a new entry.\n"; } registerName(SymbolSize); continue; @@ -1077,12 +1090,14 @@ void RewriteInstance::discoverFileObjects() { PreviousFunction->getAddress() != SymbolAddress) { if (PreviousFunction->isSymbolValidInScope(Symbol, SymbolSize)) { if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: skipping possibly another entry for function " - << *PreviousFunction << " : " << UniqueName << '\n'; + BC->outs() + << "BOLT-INFO: skipping possibly another entry for function " + << *PreviousFunction << " : " << UniqueName << '\n'; registerName(SymbolSize); } else { - outs() << "BOLT-INFO: using " << UniqueName << " as another entry to " - << "function " << *PreviousFunction << '\n'; + BC->outs() << "BOLT-INFO: using " << UniqueName + << " as another entry to " + << "function " << *PreviousFunction << '\n'; registerName(0); @@ -1114,20 +1129,21 @@ void RewriteInstance::discoverFileObjects() { uint64_t PrevLength = PrevFDE.getAddressRange(); if (SymbolAddress > PrevStart && SymbolAddress < PrevStart + PrevLength) { - errs() << "BOLT-ERROR: function " << UniqueName - << " is in conflict with FDE [" - << Twine::utohexstr(PrevStart) << ", " - << Twine::utohexstr(PrevStart + PrevLength) - << "). Skipping.\n"; + BC->errs() << "BOLT-ERROR: function " << UniqueName + << " is in conflict with FDE [" + << Twine::utohexstr(PrevStart) << ", " + << Twine::utohexstr(PrevStart + PrevLength) + << "). Skipping.\n"; IsSimple = false; } } } else if (FDE.getAddressRange() != SymbolSize) { if (SymbolSize) { // Function addresses match but sizes differ. - errs() << "BOLT-WARNING: sizes differ for function " << UniqueName - << ". FDE : " << FDE.getAddressRange() - << "; symbol table : " << SymbolSize << ". Using max size.\n"; + BC->errs() << "BOLT-WARNING: sizes differ for function " << UniqueName + << ". FDE : " << FDE.getAddressRange() + << "; symbol table : " << SymbolSize + << ". Using max size.\n"; } SymbolSize = std::max(SymbolSize, FDE.getAddressRange()); if (BC->getBinaryDataAtAddress(SymbolAddress)) { @@ -1151,10 +1167,11 @@ void RewriteInstance::discoverFileObjects() { if (SymbolSize != BF->getSize()) { if (opts::Verbosity >= 1) { if (SymbolSize && BF->getSize()) - errs() << "BOLT-WARNING: size mismatch for duplicate entries " - << *BF << " and " << UniqueName << '\n'; - outs() << "BOLT-INFO: adjusting size of function " << *BF << " old " - << BF->getSize() << " new " << SymbolSize << "\n"; + BC->errs() << "BOLT-WARNING: size mismatch for duplicate entries " + << *BF << " and " << UniqueName << '\n'; + BC->outs() << "BOLT-INFO: adjusting size of function " << *BF + << " old " << BF->getSize() << " new " << SymbolSize + << "\n"; } BF->setSize(std::max(SymbolSize, BF->getSize())); BC->setBinaryDataSize(SymbolAddress, BF->getSize()); @@ -1165,9 +1182,9 @@ void RewriteInstance::discoverFileObjects() { BC->getSectionForAddress(SymbolAddress); // Skip symbols from invalid sections if (!Section) { - errs() << "BOLT-WARNING: " << UniqueName << " (0x" - << Twine::utohexstr(SymbolAddress) - << ") does not have any section\n"; + BC->errs() << "BOLT-WARNING: " << UniqueName << " (0x" + << Twine::utohexstr(SymbolAddress) + << ") does not have any section\n"; continue; } @@ -1186,12 +1203,12 @@ void RewriteInstance::discoverFileObjects() { static bool PrintedWarning = false; if (!PrintedWarning) { PrintedWarning = true; - errs() << "BOLT-WARNING: split function detected on input : " - << SymName; + BC->errs() << "BOLT-WARNING: split function detected on input : " + << SymName; if (BC->HasRelocations) - errs() << ". The support is limited in relocation mode\n"; + BC->errs() << ". The support is limited in relocation mode\n"; else - errs() << '\n'; + BC->errs() << '\n'; } BC->HasSplitFunctions = true; BF->IsFragment = true; @@ -1222,16 +1239,16 @@ void RewriteInstance::discoverFileObjects() { BF = BC->getBinaryFunctionContainingAddress(Address); if (BF) { - errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Address) << ", 0x" - << Twine::utohexstr(Address + FDE->getAddressRange()) - << ") conflicts with function " << *BF << '\n'; + BC->errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Address) + << ", 0x" << Twine::utohexstr(Address + FDE->getAddressRange()) + << ") conflicts with function " << *BF << '\n'; continue; } if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Address) << ", 0x" - << Twine::utohexstr(Address + FDE->getAddressRange()) - << ") has no corresponding symbol table entry\n"; + BC->errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Address) + << ", 0x" << Twine::utohexstr(Address + FDE->getAddressRange()) + << ") has no corresponding symbol table entry\n"; ErrorOr Section = BC->getSectionForAddress(Address); assert(Section && "cannot get section for address from FDE"); @@ -1283,7 +1300,8 @@ void RewriteInstance::discoverFileObjects() { /*UseMaxSize*/ true); if (BF) { assert(Rel.isRelative() && "Expected relative relocation for island"); - BF->markIslandDynamicRelocationAtAddress(RelAddress); + BC->logBOLTErrorsAndQuitOnFatal( + BF->markIslandDynamicRelocationAtAddress(RelAddress)); } } } @@ -1395,23 +1413,24 @@ void RewriteInstance::registerFragments() { } if (!BD) { if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: parent function not found for " << Name << "\n"; + BC->outs() << "BOLT-INFO: parent function not found for " << Name + << "\n"; continue; } const uint64_t Address = BD->getAddress(); BinaryFunction *BF = BC->getBinaryFunctionAtAddress(Address); if (!BF) { if (opts::Verbosity >= 1) - outs() << formatv("BOLT-INFO: parent function not found at {0:x}\n", - Address); + BC->outs() << formatv( + "BOLT-INFO: parent function not found at {0:x}\n", Address); continue; } BC->registerFragment(Function, *BF); ++ParentsFound; } if (!ParentsFound) { - errs() << "BOLT-ERROR: parent function not found for " << Function - << '\n'; + BC->errs() << "BOLT-ERROR: parent function not found for " << Function + << '\n'; exit(1); } } @@ -1449,7 +1468,7 @@ void RewriteInstance::createPLTBinaryFunction(uint64_t TargetAddress, // IFUNC trampoline without symbol BinaryFunction *TargetBF = BC->getBinaryFunctionAtAddress(Rel->Addend); if (!TargetBF) { - errs() + BC->errs() << "BOLT-WARNING: Expected BF to be presented as IFUNC resolver at " << Twine::utohexstr(Rel->Addend) << ", skipping\n"; return; @@ -1483,8 +1502,9 @@ void RewriteInstance::disassemblePLTInstruction(const BinarySection &Section, if (!BC->DisAsm->getInstruction(Instruction, InstrSize, PLTData.slice(InstrOffset), InstrAddr, nulls())) { - errs() << "BOLT-ERROR: unable to disassemble instruction in PLT section " - << Section.getName() << formatv(" at offset {0:x}\n", InstrOffset); + BC->errs() + << "BOLT-ERROR: unable to disassemble instruction in PLT section " + << Section.getName() << formatv(" at offset {0:x}\n", InstrOffset); exit(1); } } @@ -1546,9 +1566,10 @@ void RewriteInstance::disassemblePLTSectionRISCV(BinarySection &Section) { if (!BC->DisAsm->getInstruction(Instruction, InstrSize, PLTData.slice(InstrOffset), InstrAddr, nulls())) { - errs() << "BOLT-ERROR: unable to disassemble instruction in PLT section " - << Section.getName() << " at offset 0x" - << Twine::utohexstr(InstrOffset) << '\n'; + BC->errs() + << "BOLT-ERROR: unable to disassemble instruction in PLT section " + << Section.getName() << " at offset 0x" + << Twine::utohexstr(InstrOffset) << '\n'; exit(1); } }; @@ -1606,8 +1627,8 @@ void RewriteInstance::disassemblePLTSectionX86(BinarySection &Section, if (!BC->MIB->evaluateMemOperandTarget(Instruction, TargetAddress, SectionAddress + InstrOffset, InstrSize)) { - errs() << "BOLT-ERROR: error evaluating PLT instruction at offset 0x" - << Twine::utohexstr(SectionAddress + InstrOffset) << '\n'; + BC->errs() << "BOLT-ERROR: error evaluating PLT instruction at offset 0x" + << Twine::utohexstr(SectionAddress + InstrOffset) << '\n'; exit(1); } @@ -1714,8 +1735,8 @@ void RewriteInstance::adjustFunctionBoundaries() { const uint64_t MaxSize = NextObjectAddress - Function.getAddress(); if (MaxSize < Function.getSize()) { - errs() << "BOLT-ERROR: symbol seen in the middle of the function " - << Function << ". Skipping.\n"; + BC->errs() << "BOLT-ERROR: symbol seen in the middle of the function " + << Function << ". Skipping.\n"; Function.setSimple(false); Function.setMaxSize(Function.getSize()); continue; @@ -1725,8 +1746,8 @@ void RewriteInstance::adjustFunctionBoundaries() { // Some assembly functions have their size set to 0, use the max // size as their real size. if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: setting size of function " << Function << " to " - << Function.getMaxSize() << " (was 0)\n"; + BC->outs() << "BOLT-INFO: setting size of function " << Function + << " to " << Function.getMaxSize() << " (was 0)\n"; Function.setSize(Function.getMaxSize()); } } @@ -1812,8 +1833,8 @@ Error RewriteInstance::readSpecialSections() { markGnuRelroSections(); if (HasDebugInfo && !opts::UpdateDebugSections && !opts::AggregateOnly) { - errs() << "BOLT-WARNING: debug info will be stripped from the binary. " - "Use -update-debug-sections to keep it.\n"; + BC->errs() << "BOLT-WARNING: debug info will be stripped from the binary. " + "Use -update-debug-sections to keep it.\n"; } HasTextRelocations = (bool)BC->getUniqueSectionByName(".rela.text"); @@ -1825,22 +1846,23 @@ Error RewriteInstance::readSpecialSections() { BC->getUniqueSectionByName(BoltAddressTranslation::SECTION_NAME)) { // Do not read BAT when plotting a heatmap if (!opts::HeatmapMode) { - if (std::error_code EC = BAT->parse(BATSec->getContents())) { - errs() << "BOLT-ERROR: failed to parse BOLT address translation " - "table.\n"; + if (std::error_code EC = BAT->parse(BC->outs(), BATSec->getContents())) { + BC->errs() << "BOLT-ERROR: failed to parse BOLT address translation " + "table.\n"; exit(1); } } } if (opts::PrintSections) { - outs() << "BOLT-INFO: Sections from original binary:\n"; - BC->printSections(outs()); + BC->outs() << "BOLT-INFO: Sections from original binary:\n"; + BC->printSections(BC->outs()); } if (opts::RelocationMode == cl::BOU_TRUE && !HasTextRelocations) { - errs() << "BOLT-ERROR: relocations against code are missing from the input " - "file. Cannot proceed in relocations mode (-relocs).\n"; + BC->errs() + << "BOLT-ERROR: relocations against code are missing from the input " + "file. Cannot proceed in relocations mode (-relocs).\n"; exit(1); } @@ -1848,15 +1870,16 @@ Error RewriteInstance::readSpecialSections() { HasTextRelocations && (opts::RelocationMode != cl::BOU_FALSE); if (BC->IsLinuxKernel && BC->HasRelocations) { - outs() << "BOLT-INFO: disabling relocation mode for Linux kernel\n"; + BC->outs() << "BOLT-INFO: disabling relocation mode for Linux kernel\n"; BC->HasRelocations = false; } BC->IsStripped = !HasSymbolTable; if (BC->IsStripped && !opts::AllowStripped) { - errs() << "BOLT-ERROR: stripped binaries are not supported. If you know " - "what you're doing, use --allow-stripped to proceed"; + BC->errs() + << "BOLT-ERROR: stripped binaries are not supported. If you know " + "what you're doing, use --allow-stripped to proceed"; exit(1); } @@ -1865,14 +1888,14 @@ Error RewriteInstance::readSpecialSections() { BC->HasRelocations = false; if (BC->HasRelocations) - outs() << "BOLT-INFO: enabling " << (opts::StrictMode ? "strict " : "") - << "relocation mode\n"; + BC->outs() << "BOLT-INFO: enabling " << (opts::StrictMode ? "strict " : "") + << "relocation mode\n"; // Read EH frame for function boundaries info. Expected EHFrameOrError = BC->DwCtx->getEHFrame(); if (!EHFrameOrError) report_error("expected valid eh_frame section", EHFrameOrError.takeError()); - CFIRdWrt.reset(new CFIReaderWriter(*EHFrameOrError.get())); + CFIRdWrt.reset(new CFIReaderWriter(*BC, *EHFrameOrError.get())); // Parse build-id parseBuildID(); @@ -1885,63 +1908,68 @@ Error RewriteInstance::readSpecialSections() { void RewriteInstance::adjustCommandLineOptions() { if (BC->isAArch64() && !BC->HasRelocations) - errs() << "BOLT-WARNING: non-relocation mode for AArch64 is not fully " - "supported\n"; + BC->errs() << "BOLT-WARNING: non-relocation mode for AArch64 is not fully " + "supported\n"; if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary()) RtLibrary->adjustCommandLineOptions(*BC); if (opts::AlignMacroOpFusion != MFT_NONE && !BC->isX86()) { - outs() << "BOLT-INFO: disabling -align-macro-fusion on non-x86 platform\n"; + BC->outs() + << "BOLT-INFO: disabling -align-macro-fusion on non-x86 platform\n"; opts::AlignMacroOpFusion = MFT_NONE; } if (BC->isX86() && BC->MAB->allowAutoPadding()) { if (!BC->HasRelocations) { - errs() << "BOLT-ERROR: cannot apply mitigations for Intel JCC erratum in " - "non-relocation mode\n"; + BC->errs() + << "BOLT-ERROR: cannot apply mitigations for Intel JCC erratum in " + "non-relocation mode\n"; exit(1); } - outs() << "BOLT-WARNING: using mitigation for Intel JCC erratum, layout " - "may take several minutes\n"; + BC->outs() + << "BOLT-WARNING: using mitigation for Intel JCC erratum, layout " + "may take several minutes\n"; opts::AlignMacroOpFusion = MFT_NONE; } if (opts::AlignMacroOpFusion != MFT_NONE && !BC->HasRelocations) { - outs() << "BOLT-INFO: disabling -align-macro-fusion in non-relocation " - "mode\n"; + BC->outs() << "BOLT-INFO: disabling -align-macro-fusion in non-relocation " + "mode\n"; opts::AlignMacroOpFusion = MFT_NONE; } if (opts::SplitEH && !BC->HasRelocations) { - errs() << "BOLT-WARNING: disabling -split-eh in non-relocation mode\n"; + BC->errs() << "BOLT-WARNING: disabling -split-eh in non-relocation mode\n"; opts::SplitEH = false; } if (opts::StrictMode && !BC->HasRelocations) { - errs() << "BOLT-WARNING: disabling strict mode (-strict) in non-relocation " - "mode\n"; + BC->errs() + << "BOLT-WARNING: disabling strict mode (-strict) in non-relocation " + "mode\n"; opts::StrictMode = false; } if (BC->HasRelocations && opts::AggregateOnly && !opts::StrictMode.getNumOccurrences()) { - outs() << "BOLT-INFO: enabling strict relocation mode for aggregation " - "purposes\n"; + BC->outs() << "BOLT-INFO: enabling strict relocation mode for aggregation " + "purposes\n"; opts::StrictMode = true; } if (BC->isX86() && BC->HasRelocations && opts::AlignMacroOpFusion == MFT_HOT && !ProfileReader) { - outs() << "BOLT-INFO: enabling -align-macro-fusion=all since no profile " - "was specified\n"; + BC->outs() + << "BOLT-INFO: enabling -align-macro-fusion=all since no profile " + "was specified\n"; opts::AlignMacroOpFusion = MFT_ALL; } if (!BC->HasRelocations && opts::ReorderFunctions != ReorderFunctions::RT_NONE) { - errs() << "BOLT-ERROR: function reordering only works when " - << "relocations are enabled\n"; + BC->errs() << "BOLT-ERROR: function reordering only works when " + << "relocations are enabled\n"; exit(1); } @@ -1950,7 +1978,7 @@ void RewriteInstance::adjustCommandLineOptions() { !opts::HotText.getNumOccurrences())) { opts::HotText = true; } else if (opts::HotText && !BC->HasRelocations) { - errs() << "BOLT-WARNING: hot text is disabled in non-relocation mode\n"; + BC->errs() << "BOLT-WARNING: hot text is disabled in non-relocation mode\n"; opts::HotText = false; } @@ -1961,12 +1989,13 @@ void RewriteInstance::adjustCommandLineOptions() { } if (opts::UseOldText && !BC->OldTextSectionAddress) { - errs() << "BOLT-WARNING: cannot use old .text as the section was not found" - "\n"; + BC->errs() + << "BOLT-WARNING: cannot use old .text as the section was not found" + "\n"; opts::UseOldText = false; } if (opts::UseOldText && !BC->HasRelocations) { - errs() << "BOLT-WARNING: cannot use old .text in non-relocation mode\n"; + BC->errs() << "BOLT-WARNING: cannot use old .text in non-relocation mode\n"; opts::UseOldText = false; } @@ -1981,23 +2010,25 @@ void RewriteInstance::adjustCommandLineOptions() { opts::Lite = true; if (opts::Lite && opts::UseOldText) { - errs() << "BOLT-WARNING: cannot combine -lite with -use-old-text. " - "Disabling -use-old-text.\n"; + BC->errs() << "BOLT-WARNING: cannot combine -lite with -use-old-text. " + "Disabling -use-old-text.\n"; opts::UseOldText = false; } if (opts::Lite && opts::StrictMode) { - errs() << "BOLT-ERROR: -strict and -lite cannot be used at the same time\n"; + BC->errs() + << "BOLT-ERROR: -strict and -lite cannot be used at the same time\n"; exit(1); } if (opts::Lite) - outs() << "BOLT-INFO: enabling lite mode\n"; + BC->outs() << "BOLT-INFO: enabling lite mode\n"; if (!opts::SaveProfile.empty() && BAT->enabledFor(InputFile)) { - errs() << "BOLT-ERROR: unable to save profile in YAML format for input " - "file processed by BOLT. Please remove -w option and use branch " - "profile.\n"; + BC->errs() + << "BOLT-ERROR: unable to save profile in YAML format for input " + "file processed by BOLT. Please remove -w option and use branch " + "profile.\n"; exit(1); } } @@ -2252,8 +2283,8 @@ void RewriteInstance::processRelocations() { } if (NumFailedRelocations) - errs() << "BOLT-WARNING: Failed to analyze " << NumFailedRelocations - << " relocations\n"; + BC->errs() << "BOLT-WARNING: Failed to analyze " << NumFailedRelocations + << " relocations\n"; } void RewriteInstance::readDynamicRelocations(const SectionRef &Section, @@ -2497,8 +2528,8 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection, assert(ContainingBF && "cannot find function for address in code"); if (!IsAArch64 && !ContainingBF->containsAddress(Rel.getOffset())) { if (opts::Verbosity >= 1) - outs() << formatv("BOLT-INFO: {0} has relocations in padding area\n", - *ContainingBF); + BC->outs() << formatv( + "BOLT-INFO: {0} has relocations in padding area\n", *ContainingBF); ContainingBF->setSize(ContainingBF->getMaxSize()); ContainingBF->setSimple(false); return; @@ -2593,12 +2624,13 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection, if (BF != ReferencedBF) { // It's possible we are referencing a function without referencing any // code, e.g. when taking a bitmask action on a function address. - errs() << "BOLT-WARNING: non-standard function reference (e.g. bitmask)" - << formatv(" detected against function {0} from ", *BF); + BC->errs() + << "BOLT-WARNING: non-standard function reference (e.g. bitmask)" + << formatv(" detected against function {0} from ", *BF); if (IsFromCode) - errs() << formatv("function {0}\n", *ContainingBF); + BC->errs() << formatv("function {0}\n", *ContainingBF); else - errs() << formatv("data section at {0:x}\n", Rel.getOffset()); + BC->errs() << formatv("data section at {0:x}\n", Rel.getOffset()); LLVM_DEBUG(printRelocationInfo(Rel, SymbolName, SymbolAddress, Addend, ExtractedValue)); ReferencedBF = BF; @@ -2628,10 +2660,11 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection, llvm::make_second_range(ContainingBF->Relocations), CheckReloc); if (Found) { - errs() << "BOLT-WARNING: detected possible compiler de-virtualization " - "bug: -1 addend used with non-pc-relative relocation against " - << formatv("function {0} in function {1}\n", *RogueBF, - *ContainingBF); + BC->errs() + << "BOLT-WARNING: detected possible compiler de-virtualization " + "bug: -1 addend used with non-pc-relative relocation against " + << formatv("function {0} in function {1}\n", *RogueBF, + *ContainingBF); return; } } @@ -2681,9 +2714,10 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection, } if (opts::Verbosity > 1 && BinarySection(*BC, RelocatedSection).isWritable()) - errs() << "BOLT-WARNING: writable reference into the middle of the " - << formatv("function {0} detected at address {1:x}\n", - *ReferencedBF, Rel.getOffset()); + BC->errs() + << "BOLT-WARNING: writable reference into the middle of the " + << formatv("function {0} detected at address {1:x}\n", + *ReferencedBF, Rel.getOffset()); } SymbolAddress = Address; Addend = 0; @@ -2825,8 +2859,9 @@ void RewriteInstance::selectFunctionsToProcess() { if ((!opts::ForceFunctionNames.empty() || !opts::ForceFunctionNamesNR.empty()) && !opts::SkipFunctionNames.empty()) { - errs() << "BOLT-ERROR: cannot select functions to process and skip at the " - "same time. Please use only one type of selection.\n"; + BC->errs() + << "BOLT-ERROR: cannot select functions to process and skip at the " + "same time. Please use only one type of selection.\n"; exit(1); } @@ -2850,8 +2885,8 @@ void RewriteInstance::selectFunctionsToProcess() { if (Index) --Index; LiteThresholdExecCount = TopFunctions[Index]->getKnownExecutionCount(); - outs() << "BOLT-INFO: limiting processing to functions with at least " - << LiteThresholdExecCount << " invocations\n"; + BC->outs() << "BOLT-INFO: limiting processing to functions with at least " + << LiteThresholdExecCount << " invocations\n"; } LiteThresholdExecCount = std::max( LiteThresholdExecCount, static_cast(opts::LiteThresholdCount)); @@ -2859,8 +2894,10 @@ void RewriteInstance::selectFunctionsToProcess() { StringSet<> ReorderFunctionsUserSet; StringSet<> ReorderFunctionsLTOCommonSet; if (opts::ReorderFunctions == ReorderFunctions::RT_USER) { - for (const std::string &Function : - ReorderFunctions::readFunctionOrderFile()) { + std::vector FunctionNames; + BC->logBOLTErrorsAndQuitOnFatal( + ReorderFunctions::readFunctionOrderFile(FunctionNames)); + for (const std::string &Function : FunctionNames) { ReorderFunctionsUserSet.insert(Function); if (std::optional LTOCommonName = getLTOCommonName(Function)) ReorderFunctionsLTOCommonSet.insert(*LTOCommonName); @@ -2936,15 +2973,15 @@ void RewriteInstance::selectFunctionsToProcess() { if (!shouldProcess(Function)) { if (opts::Verbosity >= 1) { - outs() << "BOLT-INFO: skipping processing " << Function - << " per user request\n"; + BC->outs() << "BOLT-INFO: skipping processing " << Function + << " per user request\n"; } Function.setIgnored(); } else { ++NumFunctionsToProcess; if (opts::MaxFunctions.getNumOccurrences() && NumFunctionsToProcess == opts::MaxFunctions) - outs() << "BOLT-INFO: processing ending on " << Function << '\n'; + BC->outs() << "BOLT-INFO: processing ending on " << Function << '\n'; } } @@ -2963,8 +3000,8 @@ void RewriteInstance::selectFunctionsToProcess() { if (mustSkip(Function)) { for (BinaryFunction *Parent : Function.ParentFragments) { if (opts::Verbosity >= 1) { - outs() << "BOLT-INFO: skipping processing " << *Parent - << " together with fragment function\n"; + BC->outs() << "BOLT-INFO: skipping processing " << *Parent + << " together with fragment function\n"; } Parent->setIgnored(); --NumFunctionsToProcess; @@ -2979,18 +3016,18 @@ void RewriteInstance::selectFunctionsToProcess() { }); if (IgnoredParent) { if (opts::Verbosity >= 1) { - outs() << "BOLT-INFO: skipping processing " << Function - << " together with parent function\n"; + BC->outs() << "BOLT-INFO: skipping processing " << Function + << " together with parent function\n"; } Function.setIgnored(); } else { ++NumFunctionsToProcess; if (opts::Verbosity >= 1) { - outs() << "BOLT-INFO: processing " << Function - << " as a sibling of non-ignored function\n"; + BC->outs() << "BOLT-INFO: processing " << Function + << " as a sibling of non-ignored function\n"; } if (opts::MaxFunctions && NumFunctionsToProcess == opts::MaxFunctions) - outs() << "BOLT-INFO: processing ending on " << Function << '\n'; + BC->outs() << "BOLT-INFO: processing ending on " << Function << '\n'; } } } @@ -3011,12 +3048,12 @@ void RewriteInstance::preprocessProfileData() { NamedRegionTimer T("preprocessprofile", "pre-process profile data", TimerGroupName, TimerGroupDesc, opts::TimeRewrite); - outs() << "BOLT-INFO: pre-processing profile using " - << ProfileReader->getReaderName() << '\n'; + BC->outs() << "BOLT-INFO: pre-processing profile using " + << ProfileReader->getReaderName() << '\n'; if (BAT->enabledFor(InputFile)) { - outs() << "BOLT-INFO: profile collection done on a binary already " - "processed by BOLT\n"; + BC->outs() << "BOLT-INFO: profile collection done on a binary already " + "processed by BOLT\n"; ProfileReader->setBAT(&*BAT); } @@ -3024,10 +3061,11 @@ void RewriteInstance::preprocessProfileData() { report_error("cannot pre-process profile", std::move(E)); if (!BC->hasSymbolsWithFileName() && ProfileReader->hasLocalsWithFileName()) { - errs() << "BOLT-ERROR: input binary does not have local file symbols " - "but profile data includes function names with embedded file " - "names. It appears that the input binary was stripped while a " - "profiled binary was not\n"; + BC->errs() + << "BOLT-ERROR: input binary does not have local file symbols " + "but profile data includes function names with embedded file " + "names. It appears that the input binary was stripped while a " + "profiled binary was not\n"; exit(1); } } @@ -3080,7 +3118,7 @@ void RewriteInstance::processProfileData() { if (Function.empty()) continue; - Function.print(outs(), "after attaching profile"); + Function.print(BC->outs(), "after attaching profile"); } } @@ -3109,8 +3147,8 @@ void RewriteInstance::disassembleFunctions() { ErrorOr> FunctionData = Function.getData(); if (!FunctionData) { - errs() << "BOLT-ERROR: corresponding section is non-executable or " - << "empty for function " << Function << '\n'; + BC->errs() << "BOLT-ERROR: corresponding section is non-executable or " + << "empty for function " << Function << '\n'; exit(1); } @@ -3133,21 +3171,32 @@ void RewriteInstance::disassembleFunctions() { continue; } - if (!Function.disassemble()) { - if (opts::processAllFunctions()) - BC->exitWithBugReport("function cannot be properly disassembled. " - "Unable to continue in relocation mode.", - Function); + bool DisasmFailed{false}; + handleAllErrors(Function.disassemble(), [&](const BOLTError &E) { + DisasmFailed = true; + if (E.isFatal()) { + E.log(BC->errs()); + exit(1); + } + if (opts::processAllFunctions()) { + BC->errs() << BC->generateBugReportMessage( + "function cannot be properly disassembled. " + "Unable to continue in relocation mode.", + Function); + exit(1); + } if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: could not disassemble function " << Function - << ". Will ignore.\n"; + BC->outs() << "BOLT-INFO: could not disassemble function " << Function + << ". Will ignore.\n"; // Forcefully ignore the function. Function.setIgnored(); + }); + + if (DisasmFailed) continue; - } if (opts::PrintAll || opts::PrintDisasm) - Function.print(outs(), "after disassembly"); + Function.print(BC->outs(), "after disassembly"); } BC->processInterproceduralReferences(); @@ -3182,10 +3231,12 @@ void RewriteInstance::disassembleFunctions() { // Fill in CFI information for this function if (!Function.trapsOnEntry() && !CFIRdWrt->fillCFIInfoFor(Function)) { if (BC->HasRelocations) { - BC->exitWithBugReport("unable to fill CFI.", Function); + BC->errs() << BC->generateBugReportMessage("unable to fill CFI.", + Function); + exit(1); } else { - errs() << "BOLT-WARNING: unable to fill CFI for function " << Function - << ". Skipping.\n"; + BC->errs() << "BOLT-WARNING: unable to fill CFI for function " + << Function << ". Skipping.\n"; Function.setSimple(false); continue; } @@ -3199,7 +3250,8 @@ void RewriteInstance::disassembleFunctions() { check_error(LSDASection.getError(), "failed to get LSDA section"); ArrayRef LSDAData = ArrayRef( LSDASection->getData(), LSDASection->getContents().size()); - Function.parseLSDA(LSDAData, LSDASection->getAddress()); + BC->logBOLTErrorsAndQuitOnFatal( + Function.parseLSDA(LSDAData, LSDASection->getAddress())); } } } @@ -3214,12 +3266,21 @@ void RewriteInstance::buildFunctionsCFG() { ParallelUtilities::WorkFuncWithAllocTy WorkFun = [&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId) { - if (!BF.buildCFG(AllocId)) + bool HadErrors{false}; + handleAllErrors(BF.buildCFG(AllocId), [&](const BOLTError &E) { + if (!E.getMessage().empty()) + E.log(BC->errs()); + if (E.isFatal()) + exit(1); + HadErrors = true; + }); + + if (HadErrors) return; if (opts::PrintAll) { auto L = BC->scopeLock(); - BF.print(outs(), "while building cfg"); + BF.print(BC->outs(), "while building cfg"); } }; @@ -3258,14 +3319,14 @@ void RewriteInstance::postProcessFunctions() { Function.postProcessCFG(); if (opts::PrintAll || opts::PrintCFG) - Function.print(outs(), "after building cfg"); + Function.print(BC->outs(), "after building cfg"); if (opts::DumpDotAll) Function.dumpGraphForPass("00_build-cfg"); if (opts::PrintLoopInfo) { Function.calculateLoopInfo(); - Function.printLoopInfo(outs()); + Function.printLoopInfo(BC->outs()); } BC->TotalScore += Function.getFunctionScore(); @@ -3273,15 +3334,15 @@ void RewriteInstance::postProcessFunctions() { } if (opts::PrintGlobals) { - outs() << "BOLT-INFO: Global symbols:\n"; - BC->printGlobalSymbols(outs()); + BC->outs() << "BOLT-INFO: Global symbols:\n"; + BC->printGlobalSymbols(BC->outs()); } } void RewriteInstance::runOptimizationPasses() { NamedRegionTimer T("runOptimizationPasses", "run optimization passes", TimerGroupName, TimerGroupDesc, opts::TimeRewrite); - BinaryFunctionPassManager::runAllPasses(*BC); + BC->logBOLTErrorsAndQuitOnFatal(BinaryFunctionPassManager::runAllPasses(*BC)); } void RewriteInstance::preregisterSections() { @@ -3331,7 +3392,7 @@ void RewriteInstance::emitAndLink() { Streamer->finish(); if (Streamer->getContext().hadError()) { - errs() << "BOLT-ERROR: Emission failed.\n"; + BC->errs() << "BOLT-ERROR: Emission failed.\n"; exit(1); } @@ -3342,9 +3403,10 @@ void RewriteInstance::emitAndLink() { raw_fd_ostream FOS(OutObjectPath, EC); check_error(EC, "cannot create output object file"); FOS << ObjectBuffer; - outs() << "BOLT-INFO: intermediary output object file saved for debugging " - "purposes: " - << OutObjectPath << "\n"; + BC->outs() + << "BOLT-INFO: intermediary output object file saved for debugging " + "purposes: " + << OutObjectPath << "\n"; } ErrorOr TextSection = @@ -3409,8 +3471,8 @@ void RewriteInstance::emitAndLink() { } if (opts::PrintCacheMetrics) { - outs() << "BOLT-INFO: cache metrics after emitting functions:\n"; - CacheMetrics::printAll(BC->getSortedFunctions()); + BC->outs() << "BOLT-INFO: cache metrics after emitting functions:\n"; + CacheMetrics::printAll(BC->outs(), BC->getSortedFunctions()); } } @@ -3576,14 +3638,15 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) { allocateAt(BC->OldTextSectionAddress) - BC->OldTextSectionAddress; if (CodeSize <= BC->OldTextSectionSize) { - outs() << "BOLT-INFO: using original .text for new code with 0x" - << Twine::utohexstr(opts::AlignText) << " alignment\n"; + BC->outs() << "BOLT-INFO: using original .text for new code with 0x" + << Twine::utohexstr(opts::AlignText) << " alignment\n"; AllocationDone = true; } else { - errs() << "BOLT-WARNING: original .text too small to fit the new code" - << " using 0x" << Twine::utohexstr(opts::AlignText) - << " alignment. " << CodeSize << " bytes needed, have " - << BC->OldTextSectionSize << " bytes available.\n"; + BC->errs() + << "BOLT-WARNING: original .text too small to fit the new code" + << " using 0x" << Twine::utohexstr(opts::AlignText) + << " alignment. " << CodeSize << " bytes needed, have " + << BC->OldTextSectionSize << " bytes available.\n"; opts::UseOldText = false; } } @@ -3604,9 +3667,9 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) { // Check if we need to insert a padding section for hot text. if (PaddingSize && !opts::UseOldText) - outs() << "BOLT-INFO: padding code to 0x" - << Twine::utohexstr(NextAvailableAddress) - << " to accommodate hot text\n"; + BC->outs() << "BOLT-INFO: padding code to 0x" + << Twine::utohexstr(NextAvailableAddress) + << " to accommodate hot text\n"; return; } @@ -3631,6 +3694,7 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) { Function.setImageAddress(FuncSection->getAllocAddress()); Function.setImageSize(FuncSection->getOutputSize()); if (Function.getImageSize() > Function.getMaxSize()) { + assert(!BC->isX86() && "Unexpected large function."); TooLarge = true; FailedAddresses.emplace_back(Function.getAddress()); } @@ -3814,7 +3878,7 @@ void RewriteInstance::patchELFPHDRTable() { assert(!PHDRTableAddress && "unexpected address for program header table"); PHDRTableOffset = Obj.getHeader().e_phoff; if (NewWritableSegmentSize) { - errs() << "Unable to add writable segment with UseGnuStack option\n"; + BC->errs() << "Unable to add writable segment with UseGnuStack option\n"; exit(1); } } @@ -4114,7 +4178,8 @@ void RewriteInstance::encodeBATSection() { copyByteArray(BoltInfo), BoltInfo.size(), /*Alignment=*/1, /*IsReadOnly=*/true, ELF::SHT_NOTE); - outs() << "BOLT-INFO: BAT section size (bytes): " << BoltInfo.size() << '\n'; + BC->outs() << "BOLT-INFO: BAT section size (bytes): " << BoltInfo.size() + << '\n'; } template @@ -4175,14 +4240,14 @@ RewriteInstance::getOutputSections(ELFObjectFile *File, if (Section.hasSectionRef() || Section.isAnonymous()) { if (opts::Verbosity) - outs() << "BOLT-INFO: not writing section header for section " - << Section.getOutputName() << '\n'; + BC->outs() << "BOLT-INFO: not writing section header for section " + << Section.getOutputName() << '\n'; continue; } if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: writing section header for " - << Section.getOutputName() << '\n'; + BC->outs() << "BOLT-INFO: writing section header for " + << Section.getOutputName() << '\n'; ELFShdrTy NewSection; NewSection.sh_type = ELF::SHT_PROGBITS; NewSection.sh_addr = Section.getOutputAddress(); @@ -4216,8 +4281,8 @@ RewriteInstance::getOutputSections(ELFObjectFile *File, if (PrevSection && PrevSection->sh_offset + PrevSection->sh_size > Section.sh_offset) { if (opts::Verbosity > 1) { - outs() << "BOLT-INFO: adjusting size for section " - << PrevBinSec->getOutputName() << '\n'; + BC->outs() << "BOLT-INFO: adjusting size for section " + << PrevBinSec->getOutputName() << '\n'; } PrevSection->sh_size = Section.sh_offset - PrevSection->sh_offset; } @@ -4264,8 +4329,8 @@ RewriteInstance::getOutputSections(ELFObjectFile *File, continue; if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: writing section header for " - << Section.getOutputName() << '\n'; + BC->outs() << "BOLT-INFO: writing section header for " + << Section.getOutputName() << '\n'; ELFShdrTy NewSection; NewSection.sh_type = Section.getELFType(); @@ -4663,8 +4728,8 @@ void RewriteInstance::updateELFSymbolTable( std::optional Value = std::nullopt) { NewSymbol.st_value = Value ? *Value : getNewValueForSymbol(Name); NewSymbol.st_shndx = ELF::SHN_ABS; - outs() << "BOLT-INFO: setting " << Name << " to 0x" - << Twine::utohexstr(NewSymbol.st_value) << '\n'; + BC->outs() << "BOLT-INFO: setting " << Name << " to 0x" + << Twine::utohexstr(NewSymbol.st_value) << '\n'; }; if (opts::HotText && @@ -4739,8 +4804,8 @@ void RewriteInstance::updateELFSymbolTable( Symbol.st_other = 0; Symbol.setBindingAndType(ELF::STB_WEAK, ELF::STT_NOTYPE); - outs() << "BOLT-INFO: setting " << Name << " to 0x" - << Twine::utohexstr(Symbol.st_value) << '\n'; + BC->outs() << "BOLT-INFO: setting " << Name << " to 0x" + << Twine::utohexstr(Symbol.st_value) << '\n'; Symbols.emplace_back(Symbol); }; @@ -4836,7 +4901,7 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile *File) { } } if (!SymTabSection) { - errs() << "BOLT-WARNING: no symbol table found\n"; + BC->errs() << "BOLT-WARNING: no symbol table found\n"; return; } @@ -4939,7 +5004,7 @@ void RewriteInstance::patchELFAllocatableRelrSection( auto WriteRelr = [&](uint64_t Value) { if (RelrDynOffset + DynamicRelrEntrySize > RelrDynEndOffset) { - errs() << "BOLT-ERROR: Offset overflow for relr.dyn section\n"; + BC->errs() << "BOLT-ERROR: Offset overflow for relr.dyn section\n"; exit(1); } @@ -5051,12 +5116,12 @@ RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile *File) { const uint64_t &EndOffset = IsJmpRel ? RelPltEndOffset : RelDynEndOffset; if (!Offset || !EndOffset) { - errs() << "BOLT-ERROR: Invalid offsets for dynamic relocation\n"; + BC->errs() << "BOLT-ERROR: Invalid offsets for dynamic relocation\n"; exit(1); } if (Offset + sizeof(NewRelA) > EndOffset) { - errs() << "BOLT-ERROR: Offset overflow for dynamic relocation\n"; + BC->errs() << "BOLT-ERROR: Offset overflow for dynamic relocation\n"; exit(1); } @@ -5105,7 +5170,7 @@ void RewriteInstance::patchELFGOT(ELFObjectFile *File) { } if (!GOTSection.getObject()) { if (!BC->IsStaticExecutable) - errs() << "BOLT-INFO: no .got section found\n"; + BC->errs() << "BOLT-INFO: no .got section found\n"; return; } @@ -5209,9 +5274,10 @@ void RewriteInstance::patchELFDynamic(ELFObjectFile *File) { } if (BC->RequiresZNow && !ZNowSet) { - errs() << "BOLT-ERROR: output binary requires immediate relocation " - "processing which depends on DT_FLAGS or DT_FLAGS_1 presence in " - ".dynamic. Please re-link the binary with -znow.\n"; + BC->errs() + << "BOLT-ERROR: output binary requires immediate relocation " + "processing which depends on DT_FLAGS or DT_FLAGS_1 presence in " + ".dynamic. Please re-link the binary with -znow.\n"; exit(1); } } @@ -5233,7 +5299,7 @@ Error RewriteInstance::readELFDynamic(ELFObjectFile *File) { } if (!DynamicPhdr) { - outs() << "BOLT-INFO: static input executable detected\n"; + BC->outs() << "BOLT-INFO: static input executable detected\n"; // TODO: static PIE executable might have dynamic header BC->IsStaticExecutable = true; return Error::success(); @@ -5307,12 +5373,12 @@ Error RewriteInstance::readELFDynamic(ELFObjectFile *File) { DynamicRelrAddress.reset(); DynamicRelrSize = 0; } else if (!DynamicRelrEntrySize) { - errs() << "BOLT-ERROR: expected DT_RELRENT to be presented " - << "in DYNAMIC section\n"; + BC->errs() << "BOLT-ERROR: expected DT_RELRENT to be presented " + << "in DYNAMIC section\n"; exit(1); } else if (DynamicRelrSize % DynamicRelrEntrySize) { - errs() << "BOLT-ERROR: expected RELR table size to be divisible " - << "by RELR entry size\n"; + BC->errs() << "BOLT-ERROR: expected RELR table size to be divisible " + << "by RELR entry size\n"; exit(1); } @@ -5367,12 +5433,13 @@ void RewriteInstance::rewriteFile() { continue; if (Function->getImageSize() > Function->getMaxSize()) { + assert(!BC->isX86() && "Unexpected large function."); if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: new function size (0x" - << Twine::utohexstr(Function->getImageSize()) - << ") is larger than maximum allowed size (0x" - << Twine::utohexstr(Function->getMaxSize()) << ") for function " - << *Function << '\n'; + BC->errs() << "BOLT-WARNING: new function size (0x" + << Twine::utohexstr(Function->getImageSize()) + << ") is larger than maximum allowed size (0x" + << Twine::utohexstr(Function->getMaxSize()) + << ") for function " << *Function << '\n'; // Remove jump table sections that this function owns in non-reloc mode // because we don't want to write them anymore. @@ -5408,7 +5475,7 @@ void RewriteInstance::rewriteFile() { // Overwrite function in the output file. if (opts::Verbosity >= 2) - outs() << "BOLT: rewriting function \"" << *Function << "\"\n"; + BC->outs() << "BOLT: rewriting function \"" << *Function << "\"\n"; OS.pwrite(reinterpret_cast(Function->getImageAddress()), Function->getImageSize(), Function->getFileOffset()); @@ -5428,8 +5495,8 @@ void RewriteInstance::rewriteFile() { // Write cold part if (opts::Verbosity >= 2) { - outs() << formatv("BOLT: rewriting function \"{0}\" (split parts)\n", - *Function); + BC->outs() << formatv("BOLT: rewriting function \"{0}\" (split parts)\n", + *Function); } for (const FunctionFragment &FF : @@ -5441,14 +5508,15 @@ void RewriteInstance::rewriteFile() { // Print function statistics for non-relocation mode. if (!BC->HasRelocations) { - outs() << "BOLT: " << CountOverwrittenFunctions << " out of " - << BC->getBinaryFunctions().size() - << " functions were overwritten.\n"; + BC->outs() << "BOLT: " << CountOverwrittenFunctions << " out of " + << BC->getBinaryFunctions().size() + << " functions were overwritten.\n"; if (BC->TotalScore != 0) { double Coverage = OverwrittenScore / (double)BC->TotalScore * 100.0; - outs() << format("BOLT-INFO: rewritten functions cover %.2lf", Coverage) - << "% of the execution count of simple functions of " - "this binary\n"; + BC->outs() << format("BOLT-INFO: rewritten functions cover %.2lf", + Coverage) + << "% of the execution count of simple functions of " + "this binary\n"; } } @@ -5476,10 +5544,11 @@ void RewriteInstance::rewriteFile() { continue; if (opts::Verbosity >= 1) - outs() << "BOLT: writing new section " << Section.getName() - << "\n data at 0x" << Twine::utohexstr(Section.getAllocAddress()) - << "\n of size " << Section.getOutputSize() << "\n at offset " - << Section.getOutputFileOffset() << '\n'; + BC->outs() << "BOLT: writing new section " << Section.getName() + << "\n data at 0x" + << Twine::utohexstr(Section.getAllocAddress()) << "\n of size " + << Section.getOutputSize() << "\n at offset " + << Section.getOutputFileOffset() << '\n'; OS.pwrite(reinterpret_cast(Section.getOutputData()), Section.getOutputSize(), Section.getOutputFileOffset()); } @@ -5529,8 +5598,8 @@ void RewriteInstance::rewriteFile() { patchELFSectionHeaderTable(); if (opts::PrintSections) { - outs() << "BOLT-INFO: Sections after processing:\n"; - BC->printSections(outs()); + BC->outs() << "BOLT-INFO: Sections after processing:\n"; + BC->printSections(BC->outs()); } Out->keep(); diff --git a/bolt/lib/Target/X86/X86MCSymbolizer.cpp b/bolt/lib/Target/X86/X86MCSymbolizer.cpp index ca7fe137152fd3f31a36098e8a75552af7606ac7..0e0ad9270550c3225255bb2d7b27916fdf7ffc33 100644 --- a/bolt/lib/Target/X86/X86MCSymbolizer.cpp +++ b/bolt/lib/Target/X86/X86MCSymbolizer.cpp @@ -134,7 +134,13 @@ bool X86MCSymbolizer::tryAddingSymbolicOperand( // a PC-relative 8-byte fixup, which is what we need to cover this. The // only way to do this is to use the symbol name _GLOBAL_OFFSET_TABLE_. if (Relocation::isX86GOTPC64(Relocation->Type)) { - auto [Sym, Addend] = handleGOTPC64(*Relocation, InstAddress); + auto PairOrErr = handleGOTPC64(*Relocation, InstAddress); + if (auto E = PairOrErr.takeError()) { + Function.setSimple(false); + BC.logBOLTErrorsAndQuitOnFatal(std::move(E)); + return false; + } + auto [Sym, Addend] = *PairOrErr; addOperand(Sym, Addend); return true; } @@ -158,14 +164,16 @@ bool X86MCSymbolizer::tryAddingSymbolicOperand( return true; } -std::pair +Expected> X86MCSymbolizer::handleGOTPC64(const Relocation &R, uint64_t InstrAddr) { BinaryContext &BC = Function.getBinaryContext(); const BinaryData *GOTSymBD = BC.getGOTSymbol(); if (!GOTSymBD || !GOTSymBD->getAddress()) { - errs() << "BOLT-ERROR: R_X86_GOTPC64 relocation is present but we did " - "not detect a valid _GLOBAL_OFFSET_TABLE_ in symbol table\n"; - exit(1); + // This error is pretty serious but we can't kill the disassembler + // because of it, so don't make it fatal. Log it and warn the user. + return createNonFatalBOLTError( + "R_X86_GOTPC64 relocation is present but we did not detect " + "a valid _GLOBAL_OFFSET_TABLE_ in symbol table\n"); } // R_X86_GOTPC64 are not relative to the Reloc nor end of instruction, // but the start of the MOVABSQ instruction. So the Target Address is diff --git a/bolt/lib/Target/X86/X86MCSymbolizer.h b/bolt/lib/Target/X86/X86MCSymbolizer.h index 9ed18b69c74ce405e2cfb58a00efa6a98944846c..189941e949e33a1b6875304edfb9475c621cea1f 100644 --- a/bolt/lib/Target/X86/X86MCSymbolizer.h +++ b/bolt/lib/Target/X86/X86MCSymbolizer.h @@ -20,8 +20,8 @@ protected: BinaryFunction &Function; bool CreateNewSymbols{true}; - std::pair handleGOTPC64(const Relocation &R, - uint64_t InstrAddr); + Expected> handleGOTPC64(const Relocation &R, + uint64_t InstrAddr); public: X86MCSymbolizer(BinaryFunction &Function, bool CreateNewSymbols = true) diff --git a/bolt/test/X86/fatal-error.s b/bolt/test/X86/fatal-error.s new file mode 100644 index 0000000000000000000000000000000000000000..312d1d47429f536aa1fd96343b8100ce1888c4db --- /dev/null +++ b/bolt/test/X86/fatal-error.s @@ -0,0 +1,39 @@ +# Tests whether llvm-bolt will correctly exit with error code and printing +# fatal error message in case one occurs. Here we test opening a function +# reordering file that does not exist. + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q +# RUN: not llvm-bolt %t.exe -o %t.null \ +# RUN: --reorder-blocks=normal --reorder-functions=user \ +# RUN: --function-order=/DOES/NOT/EXIST 2>&1 \ +# RUN: | FileCheck --check-prefix=CHECK %s + +# CHECK: FATAL BOLT-ERROR: Ordered functions file "/DOES/NOT/EXIST" can't be opened + +# Sample function reordering input, based off function-order-lite.s + .globl main + .type main, %function +main: + .cfi_startproc +.LBB06: + callq func_a + retq + .cfi_endproc +.size main, .-main + + .globl func_a + .type func_a, %function +func_a: + .cfi_startproc + retq + .cfi_endproc +.size func_a, .-func_a + + .globl func_b + .type func_b, %function +func_b: + .cfi_startproc + retq + .cfi_endproc +.size func_b, .-func_b diff --git a/bolt/test/X86/log.test b/bolt/test/X86/log.test new file mode 100644 index 0000000000000000000000000000000000000000..0cbb5b625d007dab307f70f4874dd07b4d87864b --- /dev/null +++ b/bolt/test/X86/log.test @@ -0,0 +1,19 @@ +# Tests whether llvm-bolt is able to redirect logs when processing a simple +# input. If this test fails on your changes, please use BinaryContext::outs() +# to print BOLT logging instead of llvm::outs(). + +RUN: yaml2obj %p/Inputs/blarge.yaml &> %t.exe +RUN: llvm-bolt %t.exe -o %t.null --data %p/Inputs/blarge.fdata -v=2 \ +RUN: --reorder-blocks=normal --print-finalized --log-file=%t.log 2>&1 \ +RUN: | FileCheck --check-prefix=CHECK --allow-empty %s +RUN: cat %t.log | FileCheck %s --check-prefix=CHECK-LOG + +CHECK-NOT: BOLT-INFO +CHECK-NOT: BOLT-WARNING +CHECK-NOT: BOLT-ERROR + +# Check some usual BOLT output lines are being redirected to the log file +CHECK-LOG: BOLT-INFO: Target architecture +CHECK-LOG: BOLT-INFO: BOLT version +CHECK-LOG: BOLT-INFO: basic block reordering modified layout +CHECK-LOG: Binary Function "usqrt" diff --git a/bolt/tools/bat-dump/bat-dump.cpp b/bolt/tools/bat-dump/bat-dump.cpp index 71efe008d409b56595943a0efa9335a2e3831751..2e9b26cc137a8621eb2faeebdfca47dbfb031976 100644 --- a/bolt/tools/bat-dump/bat-dump.cpp +++ b/bolt/tools/bat-dump/bat-dump.cpp @@ -109,7 +109,7 @@ void dumpBATFor(llvm::object::ELFObjectFileBase *InputFile) { exit(1); } - if (std::error_code EC = BAT.parse(SectionContents)) { + if (std::error_code EC = BAT.parse(outs(), SectionContents)) { errs() << "BOLT-ERROR: failed to parse BOLT address translation " "table. Malformed BAT section\n"; exit(1); diff --git a/bolt/tools/driver/llvm-bolt.cpp b/bolt/tools/driver/llvm-bolt.cpp index cc215a5256d2ba388799c407b7a1ff342224ed4c..9b03524e9f18e8771f38a7926b3b9c50945d1153 100644 --- a/bolt/tools/driver/llvm-bolt.cpp +++ b/bolt/tools/driver/llvm-bolt.cpp @@ -63,6 +63,11 @@ BoltProfile("b", cl::aliasopt(InputDataFilename), cl::cat(BoltCategory)); +cl::opt + LogFile("log-file", + cl::desc("redirect journaling to a file instead of stdout/stderr"), + cl::Hidden, cl::cat(BoltCategory)); + static cl::opt InputDataFilename2("data2", cl::desc(""), @@ -207,6 +212,24 @@ int main(int argc, char **argv) { if (!sys::fs::exists(opts::InputFilename)) report_error(opts::InputFilename, errc::no_such_file_or_directory); + // Initialize journaling streams + raw_ostream *BOLTJournalOut = &outs(); + raw_ostream *BOLTJournalErr = &errs(); + // RAII obj to keep log file open throughout execution + std::unique_ptr LogFileStream; + if (!opts::LogFile.empty()) { + std::error_code LogEC; + LogFileStream = std::make_unique( + opts::LogFile, LogEC, sys::fs::OpenFlags::OF_None); + if (LogEC) { + errs() << "BOLT-ERROR: cannot open requested log file for writing: " + << LogEC.message() << "\n"; + exit(1); + } + BOLTJournalOut = LogFileStream.get(); + BOLTJournalErr = LogFileStream.get(); + } + // Attempt to open the binary. if (!opts::DiffOnly) { Expected> BinaryOrErr = @@ -216,7 +239,8 @@ int main(int argc, char **argv) { Binary &Binary = *BinaryOrErr.get().getBinary(); if (auto *e = dyn_cast(&Binary)) { - auto RIOrErr = RewriteInstance::create(e, argc, argv, ToolPath); + auto RIOrErr = RewriteInstance::create(e, argc, argv, ToolPath, + *BOLTJournalOut, *BOLTJournalErr); if (Error E = RIOrErr.takeError()) report_error(opts::InputFilename, std::move(E)); RewriteInstance &RI = *RIOrErr.get(); diff --git a/bolt/unittests/Core/BinaryContext.cpp b/bolt/unittests/Core/BinaryContext.cpp index 7ac1c14357596bd7b63744dda394ad47265480e3..1fbb07bca966a732c4019e1615846763f21fcf4e 100644 --- a/bolt/unittests/Core/BinaryContext.cpp +++ b/bolt/unittests/Core/BinaryContext.cpp @@ -40,7 +40,8 @@ protected: void initializeBOLT() { BC = cantFail(BinaryContext::createBinaryContext( - ObjFile.get(), true, DWARFContext::create(*ObjFile.get()))); + ObjFile.get(), true, DWARFContext::create(*ObjFile.get()), + {llvm::outs(), llvm::errs()})); ASSERT_FALSE(!BC); } diff --git a/bolt/unittests/Core/MCPlusBuilder.cpp b/bolt/unittests/Core/MCPlusBuilder.cpp index b851c756e7960e9b21d08177300f19f2b9d2db50..63448039c53e677e33bdb2e7f4472f22e297a748 100644 --- a/bolt/unittests/Core/MCPlusBuilder.cpp +++ b/bolt/unittests/Core/MCPlusBuilder.cpp @@ -50,7 +50,8 @@ protected: void initializeBolt() { BC = cantFail(BinaryContext::createBinaryContext( - ObjFile.get(), true, DWARFContext::create(*ObjFile.get()))); + ObjFile.get(), true, DWARFContext::create(*ObjFile.get()), + {llvm::outs(), llvm::errs()})); ASSERT_FALSE(!BC); BC->initializeTarget(std::unique_ptr( createMCPlusBuilder(GetParam(), BC->MIA.get(), BC->MII.get(), diff --git a/clang-tools-extra/clang-move/Move.cpp b/clang-tools-extra/clang-move/Move.cpp index 1d10348430c28182ca848ee4c630a83609f88c17..ac16803b46783e55c02f95b0b8c72ba3f8147808 100644 --- a/clang-tools-extra/clang-move/Move.cpp +++ b/clang-tools-extra/clang-move/Move.cpp @@ -133,7 +133,8 @@ public: CharSourceRange FilenameRange, OptionalFileEntryRef /*File*/, StringRef SearchPath, StringRef /*RelativePath*/, - const Module * /*Imported*/, + const Module * /*SuggestedModule*/, + bool /*ModuleImported*/, SrcMgr::CharacteristicKind /*FileType*/) override { if (auto FileEntry = SM.getFileEntryRefForID(SM.getFileID(HashLoc))) MoveTool->addIncludes(FileName, IsAngled, SearchPath, diff --git a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp index 5ecd4fb19131e438a836c2334bf377190fb053fb..5e2cc207560d33567d570099cb4896d750302a85 100644 --- a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp +++ b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp @@ -166,12 +166,12 @@ void ExpandModularHeadersPPCallbacks::InclusionDirective( SourceLocation DirectiveLoc, const Token &IncludeToken, StringRef IncludedFilename, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef IncludedFile, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, bool ModuleImported, SrcMgr::CharacteristicKind FileType) { - if (Imported) { + if (ModuleImported) { serialization::ModuleFile *MF = Compiler.getASTReader()->getModuleManager().lookup( - *Imported->getASTFile()); + *SuggestedModule->getASTFile()); handleModuleFile(MF); } parseToLocation(DirectiveLoc); diff --git a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.h b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.h index 3f6abc315e5b90f19695c158a32f7e62b6c44519..0742c21bc437205301274372df6ade955b455b10 100644 --- a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.h +++ b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.h @@ -69,7 +69,7 @@ private: bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef IncludedFile, StringRef SearchPath, StringRef RelativePath, - const Module *Imported, + const Module *SuggestedModule, bool ModuleImported, SrcMgr::CharacteristicKind FileType) override; void EndOfMainFile() override; diff --git a/clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.cpp b/clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.cpp index 084e44a714d1ff9d412238b06e028c955028c813..fb1e0e82a3149b73a09a4082534a490df5eaad74 100644 --- a/clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.cpp +++ b/clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.cpp @@ -29,7 +29,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FileNameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override; void EndOfMainFile() override; @@ -61,7 +62,7 @@ void KernelNameRestrictionCheck::registerPPCallbacks(const SourceManager &SM, void KernelNameRestrictionPPCallbacks::InclusionDirective( SourceLocation HashLoc, const Token &, StringRef FileName, bool, CharSourceRange, OptionalFileEntryRef, StringRef, StringRef, const Module *, - SrcMgr::CharacteristicKind) { + bool, SrcMgr::CharacteristicKind) { IncludeDirective ID = {HashLoc, FileName}; IncludeDirectives.push_back(std::move(ID)); } diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp index 61d89cf30813066c8a2f8672e71056a63f9bbbe9..09ba79f05575258d71be53923d5dbc94c3ebc41c 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp @@ -26,7 +26,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override; private: @@ -51,8 +52,8 @@ void SuspiciousIncludeCheck::registerPPCallbacks( void SuspiciousIncludePPCallbacks::InclusionDirective( SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, - StringRef SearchPath, StringRef RelativePath, const Module *Imported, - SrcMgr::CharacteristicKind FileType) { + StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) { if (IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import) return; diff --git a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp index 8ba8b893e03a6f3280592441086602b5cf32e580..a73d46f01d9b2df5153b20ef0c53fd6318edbaa5 100644 --- a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp @@ -82,10 +82,14 @@ void TooSmallLoopVariableCheck::registerMatchers(MatchFinder *Finder) { // We are interested in only those cases when the loop bound is a variable // value (not const, enum, etc.). StatementMatcher LoopBoundMatcher = - expr(ignoringParenImpCasts(allOf(hasType(isInteger()), - unless(integerLiteral()), - unless(hasType(isConstQualified())), - unless(hasType(enumType()))))) + expr(ignoringParenImpCasts(allOf( + hasType(isInteger()), unless(integerLiteral()), + unless(allOf( + hasType(isConstQualified()), + declRefExpr(to(varDecl(anyOf( + hasInitializer(ignoringParenImpCasts(integerLiteral())), + isConstexpr(), isConstinit())))))), + unless(hasType(enumType()))))) .bind(LoopUpperBoundName); // We use the loop increment expression only to make sure we found the right diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedLocalNonTrivialVariableCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnusedLocalNonTrivialVariableCheck.cpp index 1b763d291082b6c00125603e904213a4a27afe3c..37baae7a6f0c3aad1089507c9163ad10ac742822 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnusedLocalNonTrivialVariableCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedLocalNonTrivialVariableCheck.cpp @@ -60,6 +60,7 @@ void UnusedLocalNonTrivialVariableCheck::registerMatchers(MatchFinder *Finder) { varDecl(isLocalVarDecl(), unless(isReferenced()), unless(isExceptionVariable()), hasLocalStorage(), isDefinition(), unless(hasType(isReferenceType())), unless(hasType(isTrivial())), + unless(hasAttr(attr::Kind::Unused)), hasType(hasUnqualifiedDesugaredType( anyOf(recordType(hasDeclaration(namedDecl( matchesAnyListedName(IncludeTypes), diff --git a/clang-tools-extra/clang-tidy/llvm/IncludeOrderCheck.cpp b/clang-tools-extra/clang-tidy/llvm/IncludeOrderCheck.cpp index bdd72f85e2a27c66a611ddbf879b88cc230acd3b..4246c8c574c50df78f701fdb384ba0c94ce1e02c 100644 --- a/clang-tools-extra/clang-tidy/llvm/IncludeOrderCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/IncludeOrderCheck.cpp @@ -27,7 +27,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override; void EndOfMainFile() override; @@ -81,8 +82,8 @@ static int getPriority(StringRef Filename, bool IsAngled, bool IsMainModule) { void IncludeOrderPPCallbacks::InclusionDirective( SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, - StringRef SearchPath, StringRef RelativePath, const Module *Imported, - SrcMgr::CharacteristicKind FileType) { + StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) { // We recognize the first include as a special main module header and want // to leave it in the top position. IncludeDirective ID = {HashLoc, FilenameRange, std::string(FileName), diff --git a/clang-tools-extra/clang-tidy/llvmlibc/RestrictSystemLibcHeadersCheck.cpp b/clang-tools-extra/clang-tidy/llvmlibc/RestrictSystemLibcHeadersCheck.cpp index 3451d3474fd906a146fd3d587d3d79e2865ee050..b656917071a6ca68927a9d032922176ef4e4ce62 100644 --- a/clang-tools-extra/clang-tidy/llvmlibc/RestrictSystemLibcHeadersCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvmlibc/RestrictSystemLibcHeadersCheck.cpp @@ -33,7 +33,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override; private: @@ -45,14 +46,14 @@ private: void RestrictedIncludesPPCallbacks::InclusionDirective( SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, - StringRef SearchPath, StringRef RelativePath, const Module *Imported, - SrcMgr::CharacteristicKind FileType) { + StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) { // Compiler provided headers are allowed (e.g stddef.h). if (SrcMgr::isSystem(FileType) && SearchPath == CompilerIncudeDir) return; portability::RestrictedIncludesPPCallbacks::InclusionDirective( HashLoc, IncludeTok, FileName, IsAngled, FilenameRange, File, SearchPath, - RelativePath, Imported, FileType); + RelativePath, SuggestedModule, ModuleImported, FileType); } void RestrictSystemLibcHeadersCheck::registerPPCallbacks( diff --git a/clang-tools-extra/clang-tidy/misc/HeaderIncludeCycleCheck.cpp b/clang-tools-extra/clang-tidy/misc/HeaderIncludeCycleCheck.cpp index bebd6e390ed53c65e1c819f24b6202914e4df6ed..fadfdc869d37b05403aa190b2577e1d4411e089d 100644 --- a/clang-tools-extra/clang-tidy/misc/HeaderIncludeCycleCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/HeaderIncludeCycleCheck.cpp @@ -83,7 +83,7 @@ public: void InclusionDirective(SourceLocation, const Token &, StringRef FilePath, bool, CharSourceRange Range, OptionalFileEntryRef File, StringRef, StringRef, - const Module *, + const Module *, bool, SrcMgr::CharacteristicKind FileType) override { if (FileType != clang::SrcMgr::C_User) return; diff --git a/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp index 030a781e2099be705dd06eb0b17871fe3295c350..6a467910521f5db5e9cdac23db18aea8a744f59c 100644 --- a/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp @@ -32,7 +32,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override; private: @@ -157,7 +158,7 @@ IncludeModernizePPCallbacks::IncludeModernizePPCallbacks( {"wctype.h", "cwctype"}})) { CStyledHeaderToCxx.insert(KeyValue); } - // Add C++ 11 headers. + // Add C++11 headers. if (LangOpts.CPlusPlus11) { for (const auto &KeyValue : std::vector>( @@ -178,8 +179,8 @@ IncludeModernizePPCallbacks::IncludeModernizePPCallbacks( void IncludeModernizePPCallbacks::InclusionDirective( SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, - StringRef SearchPath, StringRef RelativePath, const Module *Imported, - SrcMgr::CharacteristicKind FileType) { + StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) { // If we don't want to warn for non-main file reports and this is one, skip // it. diff --git a/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp index b197c22dca410e42966ccae494afbaddefd8b74d..0b47ed316ca2711f5e1655d0b1f14bd065c4a590 100644 --- a/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp @@ -117,7 +117,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override { clearCurrentEnum(HashLoc); } diff --git a/clang-tools-extra/clang-tidy/portability/RestrictSystemIncludesCheck.cpp b/clang-tools-extra/clang-tidy/portability/RestrictSystemIncludesCheck.cpp index 9ee0b4e6d3ccb8d819b997de469c17278cd62589..db5693e3b7cb7d178344bf9e82ac5bd511d6bec7 100644 --- a/clang-tools-extra/clang-tidy/portability/RestrictSystemIncludesCheck.cpp +++ b/clang-tools-extra/clang-tidy/portability/RestrictSystemIncludesCheck.cpp @@ -21,8 +21,8 @@ namespace clang::tidy::portability { void RestrictedIncludesPPCallbacks::InclusionDirective( SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, - StringRef SearchPath, StringRef RelativePath, const Module *Imported, - SrcMgr::CharacteristicKind FileType) { + StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) { if (!Check.contains(FileName) && SrcMgr::isSystem(FileType)) { SmallString<256> FullPath; llvm::sys::path::append(FullPath, SearchPath); diff --git a/clang-tools-extra/clang-tidy/portability/RestrictSystemIncludesCheck.h b/clang-tools-extra/clang-tidy/portability/RestrictSystemIncludesCheck.h index ad18e6f411dbbd07dfd13005f387132b1ea7f13a..60fae5e73a60267d02cd6e43392d5971b297077e 100644 --- a/clang-tools-extra/clang-tidy/portability/RestrictSystemIncludesCheck.h +++ b/clang-tools-extra/clang-tidy/portability/RestrictSystemIncludesCheck.h @@ -50,7 +50,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override; void EndOfMainFile() override; diff --git a/clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.cpp b/clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.cpp index d1f41e0ec79e21b5e08c7bb0b5c60920560b711c..67147164946ab405138aeafbb361f490f4382ad6 100644 --- a/clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.cpp @@ -47,7 +47,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override; void MacroDefined(const Token &MacroNameTok, @@ -76,8 +77,8 @@ void DuplicateIncludeCallbacks::FileChanged(SourceLocation Loc, void DuplicateIncludeCallbacks::InclusionDirective( SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, - StringRef SearchPath, StringRef RelativePath, const Module *Imported, - SrcMgr::CharacteristicKind FileType) { + StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) { if (llvm::is_contained(Files.back(), FileName)) { // We want to delete the entire line, so make sure that [Start,End] covers // everything. diff --git a/clang-tools-extra/clang-tidy/utils/IncludeInserter.cpp b/clang-tools-extra/clang-tidy/utils/IncludeInserter.cpp index d0b7474992abd0853229a8186481dc92c5b0527f..b53016f331b793cefd5b12f774ac1c00997cd6e9 100644 --- a/clang-tools-extra/clang-tidy/utils/IncludeInserter.cpp +++ b/clang-tools-extra/clang-tidy/utils/IncludeInserter.cpp @@ -25,7 +25,8 @@ public: bool IsAngled, CharSourceRange FileNameRange, OptionalFileEntryRef /*IncludedFile*/, StringRef /*SearchPath*/, StringRef /*RelativePath*/, - const Module * /*ImportedModule*/, + const Module * /*SuggestedModule*/, + bool /*ModuleImported*/, SrcMgr::CharacteristicKind /*FileType*/) override { Inserter->addInclude(FileNameRef, IsAngled, HashLocation, IncludeToken.getEndLoc()); diff --git a/clang-tools-extra/clangd/Headers.cpp b/clang-tools-extra/clangd/Headers.cpp index 076e636e0e2819a05ac7cb08909de62c74dc9a31..75f8668e7bef06077f52b3b5404f3dba3ac15cd5 100644 --- a/clang-tools-extra/clangd/Headers.cpp +++ b/clang-tools-extra/clangd/Headers.cpp @@ -41,7 +41,8 @@ public: OptionalFileEntryRef File, llvm::StringRef /*SearchPath*/, llvm::StringRef /*RelativePath*/, - const clang::Module * /*Imported*/, + const clang::Module * /*SuggestedModule*/, + bool /*ModuleImported*/, SrcMgr::CharacteristicKind FileKind) override { auto MainFID = SM.getMainFileID(); // If an include is part of the preamble patch, translate #line directives. diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp index 14a91797f4d2ea2b8bfdc98507d76dc6cf31d7ff..bbb0e2c77b3f318c9afeca83b111e93c6b7b5423 100644 --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -244,7 +244,7 @@ private: SynthesizedFilenameTok.getEndLoc()) .toCharRange(SM), File, "SearchPath", "RelPath", - /*Imported=*/nullptr, Inc.FileKind); + /*SuggestedModule=*/nullptr, /*ModuleImported=*/false, Inc.FileKind); if (File) Delegate->FileSkipped(*File, SynthesizedFilenameTok, Inc.FileKind); } diff --git a/clang-tools-extra/clangd/index/IndexAction.cpp b/clang-tools-extra/clangd/index/IndexAction.cpp index 5d56285a839614058ce0b78c52e7a4693c0e6150..ed56c2a9d2e811acdd69405ea7326d958845f9c6 100644 --- a/clang-tools-extra/clangd/index/IndexAction.cpp +++ b/clang-tools-extra/clangd/index/IndexAction.cpp @@ -89,7 +89,8 @@ public: llvm::StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, llvm::StringRef SearchPath, - llvm::StringRef RelativePath, const Module *Imported, + llvm::StringRef RelativePath, + const Module *SuggestedModule, bool ModuleImported, SrcMgr::CharacteristicKind FileType) override { auto IncludeURI = toURI(File); if (!IncludeURI) diff --git a/clang-tools-extra/clangd/unittests/ReplayPeambleTests.cpp b/clang-tools-extra/clangd/unittests/ReplayPeambleTests.cpp index 472fe30ee46ed4b08238b912b8f02ae1fee26351..147d9abe691372a3f53c74b05d6b8599641e5a75 100644 --- a/clang-tools-extra/clangd/unittests/ReplayPeambleTests.cpp +++ b/clang-tools-extra/clangd/unittests/ReplayPeambleTests.cpp @@ -72,7 +72,7 @@ struct ReplayPreamblePPCallback : public PPCallbacks { void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef, - StringRef, StringRef, const clang::Module *, + StringRef, StringRef, const clang::Module *, bool, SrcMgr::CharacteristicKind) override { Includes.emplace_back(SM, HashLoc, IncludeTok, FileName, IsAngled, FilenameRange); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index e50914aed5f07a0c384b50b3ffd31805722a4a0b..f2fba9aa1450d68e4d70fbe5dfd49669f45ba073 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -117,6 +117,14 @@ Changes in existing checks options `HeaderFileExtensions` and `ImplementationFileExtensions` by the global options of the same name. +- Improved :doc:`bugprone-too-small-loop-variable + ` check by incorporating + better support for ``const`` loop boundaries. + +- Improved :doc:`bugprone-unused-local-non-trivial-variable + ` check by + ignoring local variable with ``[maybe_unused]`` attribute. + - Cleaned up :doc:`cppcoreguidelines-prefer-member-initializer ` by removing enforcement of rule `C.48 @@ -159,13 +167,13 @@ Changes in existing checks Removed checks ^^^^^^^^^^^^^^ -Miscellaneous -^^^^^^^^^^^^^ - - Removed `cert-dcl21-cpp`, which was deprecated since :program:`clang-tidy` 17, since the rule DCL21-CPP has been removed from the CERT guidelines. -- Fixed incorrect formatting in ``clang-apply-repalcements`` when no ``--format`` +Miscellaneous +^^^^^^^^^^^^^ + +- Fixed incorrect formatting in ``clang-apply-replacements`` when no ``--format`` option is specified. Now ``clang-apply-replacements`` applies formatting only with the option. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/too-small-loop-variable.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/too-small-loop-variable.rst index 0f45cc2fe11463ea440e4a07eb892a24b8b8663a..2c3ded952aa022c23ad4c6f5d9884aebd5fea698 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/too-small-loop-variable.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/too-small-loop-variable.rst @@ -28,6 +28,10 @@ In a real use case size means a container's size which depends on the user input This algorithm works for a small amount of objects, but will lead to freeze for a larger user input. +It's recommended to enable the compiler warning +`-Wtautological-constant-out-of-range-compare` as well, since check does not +inspect compile-time constant loop boundaries to avoid overlaps with the warning. + .. option:: MagnitudeBitsUpperLimit Upper limit for the magnitude bits of the loop variable. If it's set the check diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-local-non-trivial-variable.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-local-non-trivial-variable.rst index 7531f19f3ebc15bcf35a43bc71170c69c6bcaed3..9f283de78fbdec58e3101af9d432712bb021b5e2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-local-non-trivial-variable.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-local-non-trivial-variable.rst @@ -11,6 +11,7 @@ The following types of variables are excluded from this check: * exception variables in catch clauses * static or thread local * structured bindings +* variables with ``[[maybe_unused]]`` attribute This check can be configured to warn on all non-trivial variables by setting `IncludeTypes` to `.*`, and excluding specific types using `ExcludeTypes`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/deprecated-headers.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/deprecated-headers.rst index 974a56abd97dd25f442f6180548aa1ef5399f41d..298243fc3cedd2572ebed85203b094015167296f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/deprecated-headers.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/deprecated-headers.rst @@ -4,7 +4,7 @@ modernize-deprecated-headers ============================ Some headers from C library were deprecated in C++ and are no longer welcome in -C++ codebases. Some have no effect in C++. For more details refer to the C++ 14 +C++ codebases. Some have no effect in C++. For more details refer to the C++14 Standard [depr.c.headers] section. This check replaces C standard library headers with their C++ alternatives and diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-override.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-override.rst index 0440ab855ea7bd04654147a2e0b861efde521823..f8f34794af7494366660ad92d0c0e757498552ca 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-override.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-override.rst @@ -10,7 +10,7 @@ removes ``virtual`` from those functions as it is not required. user that a function was virtual. C++ compilers did not use the presence of this to signify an overridden function. -In C++ 11 ``override`` and ``final`` keywords were introduced to allow +In C++11 ``override`` and ``final`` keywords were introduced to allow overridden functions to be marked appropriately. Their presence allows compilers to verify that an overridden function correctly overrides a base class implementation. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/avoid-return-with-void-value.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/avoid-return-with-void-value.rst index d802f9be829c46c3d10556bd69bbda0d3eb480e9..b07958188d3137d0225f5cdd7bd4bc3690269eaf 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/avoid-return-with-void-value.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/avoid-return-with-void-value.rst @@ -29,7 +29,7 @@ that should be written as g(); return; -to make clear that ``g()`` is called and immediately afterwards the function +to make clear that ``g()`` is called and immediately afterwards the function returns (nothing). In C, the same issue is detected by the compiler if the ``-Wpedantic`` mode @@ -46,6 +46,6 @@ Options .. option:: StrictMode The value `false` specifies that a direct return statement shall - be excluded from the analysis if it is the only statement not - contained in a block like ``if (cond) return g();``. The default + be excluded from the analysis if it is the only statement not + contained in a block, like ``if (cond) return g();``. The default value is `true`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/container-contains.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/container-contains.rst index 07d1e352d3b1bd04ceabcfc2c9225701880aeca2..b28daecf7a2cf303bb80f7afc8dd2f2afb174e46 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/container-contains.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/container-contains.rst @@ -3,7 +3,7 @@ readability-container-contains ============================== -Finds usages of ``container.count()`` and ``container.find() == container.end()`` which should be replaced by a call to the ``container.contains()`` method introduced in C++ 20. +Finds usages of ``container.count()`` and ``container.find() == container.end()`` which should be replaced by a call to the ``container.contains()`` method introduced in C++20. Whether an element is contained inside a container should be checked with ``contains`` instead of ``count``/``find`` because ``contains`` conveys the intent more clearly. Furthermore, for containers which permit multiple entries per key (``multimap``, ``multiset``, ...), ``contains`` is more efficient than ``count`` because ``count`` has to do unnecessary additional work. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/use-anyofallof.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-anyofallof.rst index f7bd9ff89345b6ce60702bad4364601329f7d34d..6e58766275107b7c611e2827591d6647c6fa39e9 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/use-anyofallof.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/use-anyofallof.rst @@ -4,7 +4,7 @@ readability-use-anyofallof ========================== Finds range-based for loops that can be replaced by a call to ``std::any_of`` or -``std::all_of``. In C++ 20 mode, suggests ``std::ranges::any_of`` or +``std::all_of``. In C++20 mode, suggests ``std::ranges::any_of`` or ``std::ranges::all_of``. Example: diff --git a/clang-tools-extra/include-cleaner/lib/Record.cpp b/clang-tools-extra/include-cleaner/lib/Record.cpp index c93c56adf650d95f50e8f175620c2758f8ed255c..78a4df6cc40ea2d2e5516236a303fa1e6073ac11 100644 --- a/clang-tools-extra/include-cleaner/lib/Record.cpp +++ b/clang-tools-extra/include-cleaner/lib/Record.cpp @@ -65,7 +65,8 @@ public: StringRef SpelledFilename, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind) override { if (!Active) return; @@ -214,7 +215,8 @@ public: OptionalFileEntryRef File, llvm::StringRef /*SearchPath*/, llvm::StringRef /*RelativePath*/, - const clang::Module * /*Imported*/, + const clang::Module * /*SuggestedModule*/, + bool /*ModuleImported*/, SrcMgr::CharacteristicKind FileKind) override { FileID HashFID = SM.getFileID(HashLoc); int HashLine = SM.getLineNumber(HashFID, SM.getFileOffset(HashLoc)); diff --git a/clang-tools-extra/modularize/CoverageChecker.cpp b/clang-tools-extra/modularize/CoverageChecker.cpp index 1e8b0aa37ca309931c9d2c70433ffb22bc6018aa..0e76c539aa3c839f87de6058c7115ca7d3af6afb 100644 --- a/clang-tools-extra/modularize/CoverageChecker.cpp +++ b/clang-tools-extra/modularize/CoverageChecker.cpp @@ -90,7 +90,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override { Checker.collectUmbrellaHeaderHeader(File->getName()); } diff --git a/clang-tools-extra/modularize/PreprocessorTracker.cpp b/clang-tools-extra/modularize/PreprocessorTracker.cpp index 7557fb177ceb48a24b8bc10960daba160c19e31e..85e3aab041e49d9651937efe39123690d1c94d04 100644 --- a/clang-tools-extra/modularize/PreprocessorTracker.cpp +++ b/clang-tools-extra/modularize/PreprocessorTracker.cpp @@ -730,15 +730,14 @@ public: ~PreprocessorCallbacks() override {} // Overridden handlers. - void InclusionDirective(clang::SourceLocation HashLoc, - const clang::Token &IncludeTok, - llvm::StringRef FileName, bool IsAngled, - clang::CharSourceRange FilenameRange, - clang::OptionalFileEntryRef File, - llvm::StringRef SearchPath, - llvm::StringRef RelativePath, - const clang::Module *Imported, - clang::SrcMgr::CharacteristicKind FileType) override; + void + InclusionDirective(clang::SourceLocation HashLoc, + const clang::Token &IncludeTok, llvm::StringRef FileName, + bool IsAngled, clang::CharSourceRange FilenameRange, + clang::OptionalFileEntryRef File, + llvm::StringRef SearchPath, llvm::StringRef RelativePath, + const clang::Module *SuggestedModule, bool ModuleImported, + clang::SrcMgr::CharacteristicKind FileType) override; void FileChanged(clang::SourceLocation Loc, clang::PPCallbacks::FileChangeReason Reason, clang::SrcMgr::CharacteristicKind FileType, @@ -1275,7 +1274,8 @@ void PreprocessorCallbacks::InclusionDirective( llvm::StringRef FileName, bool IsAngled, clang::CharSourceRange FilenameRange, clang::OptionalFileEntryRef File, llvm::StringRef SearchPath, llvm::StringRef RelativePath, - const clang::Module *Imported, clang::SrcMgr::CharacteristicKind FileType) { + const clang::Module *SuggestedModule, bool ModuleImported, + clang::SrcMgr::CharacteristicKind FileType) { int DirectiveLine, DirectiveColumn; std::string HeaderPath = getSourceLocationFile(PP, HashLoc); getSourceLocationLineAndColumn(PP, HashLoc, DirectiveLine, DirectiveColumn); diff --git a/clang-tools-extra/pp-trace/PPCallbacksTracker.cpp b/clang-tools-extra/pp-trace/PPCallbacksTracker.cpp index a59a8278682b23a25f7344020ef1e12d144b247c..3bb30fd15b2e1d6d7a897e4680e0b79e5dabc811 100644 --- a/clang-tools-extra/pp-trace/PPCallbacksTracker.cpp +++ b/clang-tools-extra/pp-trace/PPCallbacksTracker.cpp @@ -135,7 +135,8 @@ void PPCallbacksTracker::InclusionDirective( SourceLocation HashLoc, const Token &IncludeTok, llvm::StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, llvm::StringRef SearchPath, llvm::StringRef RelativePath, - const Module *Imported, SrcMgr::CharacteristicKind FileType) { + const Module *SuggestedModule, bool ModuleImported, + SrcMgr::CharacteristicKind FileType) { beginCallback("InclusionDirective"); appendArgument("HashLoc", HashLoc); appendArgument("IncludeTok", IncludeTok); @@ -145,7 +146,8 @@ void PPCallbacksTracker::InclusionDirective( appendArgument("File", File); appendFilePathArgument("SearchPath", SearchPath); appendFilePathArgument("RelativePath", RelativePath); - appendArgument("Imported", Imported); + appendArgument("SuggestedModule", SuggestedModule); + appendArgument("ModuleImported", ModuleImported); } // Callback invoked whenever there was an explicit module-import diff --git a/clang-tools-extra/pp-trace/PPCallbacksTracker.h b/clang-tools-extra/pp-trace/PPCallbacksTracker.h index c195a72b08c1aad90dbbd093c6e36c1d7a7a57d5..04590a919369aebc6aec184a9194821eb1de1e55 100644 --- a/clang-tools-extra/pp-trace/PPCallbacksTracker.h +++ b/clang-tools-extra/pp-trace/PPCallbacksTracker.h @@ -95,7 +95,8 @@ public: llvm::StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, llvm::StringRef SearchPath, - llvm::StringRef RelativePath, const Module *Imported, + llvm::StringRef RelativePath, + const Module *SuggestedModule, bool ModuleImported, SrcMgr::CharacteristicKind FileType) override; void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path, const Module *Imported) override; diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/too-small-loop-variable.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/too-small-loop-variable.cpp index 3229deb93bada8033577c6a67f3792937c016d61..113150b168650bd70057e83ddb84d0c3ce344039 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/too-small-loop-variable.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/too-small-loop-variable.cpp @@ -93,6 +93,18 @@ void voidBadForLoopWithMacroBound() { } } +unsigned int getVal() { + return 300; +} + +// The iteration's upper bound has a function declaration. +void voidBadForLoop8() { + const unsigned int l = getVal(); + for (unsigned char i = 0; i < l; ++i) { + // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: loop variable has narrower type 'unsigned char' than iteration's upper bound 'const unsigned int' [bugprone-too-small-loop-variable] + } +} + //////////////////////////////////////////////////////////////////////////////// /// Correct loops: we should not warn here. diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable.cpp index 19f2344de4a650692456723648faaf36bfcf7230..3fdc24b94a6cb2b7d3080772c40c4d4b5b9c22f3 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable.cpp @@ -77,6 +77,7 @@ T qux(T Generic) { // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unused local variable 'TemplateType' of type 'async::Future' [bugprone-unused-local-non-trivial-variable] a::Future AliasTemplateType; // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: unused local variable 'AliasTemplateType' of type 'a::Future' (aka 'Future') [bugprone-unused-local-non-trivial-variable] + [[maybe_unused]] async::Future MaybeUnused; return Generic; } diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp index 547f634a101c58143e89cc80d704392237b62633..d0efc5ca7637538859ab4865eaa3e28e44a60bf1 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp @@ -68,5 +68,6 @@ auto S<>::foo(auto) { return 1; } -// CHECK8: error: template parameter list matching the non-templated nested type 'S<>' should be empty ('template<>') [clang-diagnostic-error] +// CHECK8: error: conflicting types for 'foo' [clang-diagnostic-error] +// CHECK8: note: previous declaration is here #endif diff --git a/clang-tools-extra/test/pp-trace/pp-trace-include.cpp b/clang-tools-extra/test/pp-trace/pp-trace-include.cpp index db0b2c89430a21cc9af48fc7a64c791744ec4878..ea9896e1cfde254cc99e38d8e577fc711423bed0 100644 --- a/clang-tools-extra/test/pp-trace/pp-trace-include.cpp +++ b/clang-tools-extra/test/pp-trace/pp-trace-include.cpp @@ -59,7 +59,8 @@ // CHECK-NEXT: File: "{{.*}}{{[/\\]}}Inputs/Level1A.h" // CHECK-NEXT: SearchPath: "{{.*}}{{[/\\]}}pp-trace" // CHECK-NEXT: RelativePath: "Inputs/Level1A.h" -// CHECK-NEXT: Imported: (null) +// CHECK-NEXT: SuggestedModule: (null) +// CHECK-NEXT: ModuleImported: false // CHECK-NEXT: - Callback: FileChanged // CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level1A.h:1:1" // CHECK-NEXT: Reason: EnterFile @@ -74,7 +75,8 @@ // CHECK-NEXT: File: "{{.*}}{{[/\\]}}Inputs/Level2A.h" // CHECK-NEXT: SearchPath: "{{.*}}{{[/\\]}}Inputs" // CHECK-NEXT: RelativePath: "Level2A.h" -// CHECK-NEXT: Imported: (null) +// CHECK-NEXT: SuggestedModule: (null) +// CHECK-NEXT: ModuleImported: false // CHECK-NEXT: - Callback: FileChanged // CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level2A.h:1:1" // CHECK-NEXT: Reason: EnterFile @@ -105,7 +107,8 @@ // CHECK-NEXT: File: "{{.*}}{{[/\\]}}Inputs/Level1B.h" // CHECK-NEXT: SearchPath: "{{.*}}{{[/\\]}}pp-trace" // CHECK-NEXT: RelativePath: "Inputs/Level1B.h" -// CHECK-NEXT: Imported: (null) +// CHECK-NEXT: SuggestedModule: (null) +// CHECK-NEXT: ModuleImported: false // CHECK-NEXT: - Callback: FileChanged // CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level1B.h:1:1" // CHECK-NEXT: Reason: EnterFile @@ -120,7 +123,8 @@ // CHECK-NEXT: File: "{{.*}}{{[/\\]}}Inputs/Level2B.h" // CHECK-NEXT: SearchPath: "{{.*}}{{[/\\]}}Inputs" // CHECK-NEXT: RelativePath: "Level2B.h" -// CHECK-NEXT: Imported: (null) +// CHECK-NEXT: SuggestedModule: (null) +// CHECK-NEXT: ModuleImported: false // CHECK-NEXT: - Callback: FileChanged // CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level2B.h:1:1" // CHECK-NEXT: Reason: EnterFile diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 0a8cc18c5b4cb583ce36caa8c4420bda59c0eb1a..fdf7bfaeaa4ec700b7e529efb3d04340463a926a 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1531,114 +1531,8 @@ the configuration (without a prefix: ``Auto``). .. _AlwaysBreakAfterReturnType: -**AlwaysBreakAfterReturnType** (``ReturnTypeBreakingStyle``) :versionbadge:`clang-format 3.8` :ref:`¶ ` - The function declaration return type breaking style to use. - - Possible values: - - * ``RTBS_None`` (in configuration: ``None``) - This is **deprecated**. See ``Automatic`` below. - - * ``RTBS_Automatic`` (in configuration: ``Automatic``) - Break after return type based on ``PenaltyReturnTypeOnItsOwnLine``. - - .. code-block:: c++ - - class A { - int f() { return 0; }; - }; - int f(); - int f() { return 1; } - int - LongName::AnotherLongName(); - - * ``RTBS_ExceptShortType`` (in configuration: ``ExceptShortType``) - Same as ``Automatic`` above, except that there is no break after short - return types. - - .. code-block:: c++ - - class A { - int f() { return 0; }; - }; - int f(); - int f() { return 1; } - int LongName:: - AnotherLongName(); - - * ``RTBS_All`` (in configuration: ``All``) - Always break after the return type. - - .. code-block:: c++ - - class A { - int - f() { - return 0; - }; - }; - int - f(); - int - f() { - return 1; - } - int - LongName::AnotherLongName(); - - * ``RTBS_TopLevel`` (in configuration: ``TopLevel``) - Always break after the return types of top-level functions. - - .. code-block:: c++ - - class A { - int f() { return 0; }; - }; - int - f(); - int - f() { - return 1; - } - int - LongName::AnotherLongName(); - - * ``RTBS_AllDefinitions`` (in configuration: ``AllDefinitions``) - Always break after the return type of function definitions. - - .. code-block:: c++ - - class A { - int - f() { - return 0; - }; - }; - int f(); - int - f() { - return 1; - } - int - LongName::AnotherLongName(); - - * ``RTBS_TopLevelDefinitions`` (in configuration: ``TopLevelDefinitions``) - Always break after the return type of top-level definitions. - - .. code-block:: c++ - - class A { - int f() { return 0; }; - }; - int f(); - int - f() { - return 1; - } - int - LongName::AnotherLongName(); - - +**AlwaysBreakAfterReturnType** (``deprecated``) :versionbadge:`clang-format 3.8` :ref:`¶ ` + This option is renamed to ``BreakAfterReturnType``. .. _AlwaysBreakBeforeMultilineStrings: @@ -1659,62 +1553,8 @@ the configuration (without a prefix: ``Auto``). .. _AlwaysBreakTemplateDeclarations: -**AlwaysBreakTemplateDeclarations** (``BreakTemplateDeclarationsStyle``) :versionbadge:`clang-format 3.4` :ref:`¶ ` - The template declaration breaking style to use. - - Possible values: - - * ``BTDS_Leave`` (in configuration: ``Leave``) - Do not change the line breaking before the declaration. - - .. code-block:: c++ - - template - T foo() { - } - template T foo(int aaaaaaaaaaaaaaaaaaaaa, - int bbbbbbbbbbbbbbbbbbbbb) { - } - - * ``BTDS_No`` (in configuration: ``No``) - Do not force break before declaration. - ``PenaltyBreakTemplateDeclaration`` is taken into account. - - .. code-block:: c++ - - template T foo() { - } - template T foo(int aaaaaaaaaaaaaaaaaaaaa, - int bbbbbbbbbbbbbbbbbbbbb) { - } - - * ``BTDS_MultiLine`` (in configuration: ``MultiLine``) - Force break after template declaration only when the following - declaration spans multiple lines. - - .. code-block:: c++ - - template T foo() { - } - template - T foo(int aaaaaaaaaaaaaaaaaaaaa, - int bbbbbbbbbbbbbbbbbbbbb) { - } - - * ``BTDS_Yes`` (in configuration: ``Yes``) - Always break after template declaration. - - .. code-block:: c++ - - template - T foo() { - } - template - T foo(int aaaaaaaaaaaaaaaaaaaaa, - int bbbbbbbbbbbbbbbbbbbbb) { - } - - +**AlwaysBreakTemplateDeclarations** (``deprecated``) :versionbadge:`clang-format 3.4` :ref:`¶ ` + This option is renamed to ``BreakTemplateDeclarations``. .. _AttributeMacros: @@ -2273,6 +2113,117 @@ the configuration (without a prefix: ``Auto``). @Mock DataLoad loader; +.. _BreakAfterReturnType: + +**BreakAfterReturnType** (``ReturnTypeBreakingStyle``) :versionbadge:`clang-format 19` :ref:`¶ ` + The function declaration return type breaking style to use. + + Possible values: + + * ``RTBS_None`` (in configuration: ``None``) + This is **deprecated**. See ``Automatic`` below. + + * ``RTBS_Automatic`` (in configuration: ``Automatic``) + Break after return type based on ``PenaltyReturnTypeOnItsOwnLine``. + + .. code-block:: c++ + + class A { + int f() { return 0; }; + }; + int f(); + int f() { return 1; } + int + LongName::AnotherLongName(); + + * ``RTBS_ExceptShortType`` (in configuration: ``ExceptShortType``) + Same as ``Automatic`` above, except that there is no break after short + return types. + + .. code-block:: c++ + + class A { + int f() { return 0; }; + }; + int f(); + int f() { return 1; } + int LongName:: + AnotherLongName(); + + * ``RTBS_All`` (in configuration: ``All``) + Always break after the return type. + + .. code-block:: c++ + + class A { + int + f() { + return 0; + }; + }; + int + f(); + int + f() { + return 1; + } + int + LongName::AnotherLongName(); + + * ``RTBS_TopLevel`` (in configuration: ``TopLevel``) + Always break after the return types of top-level functions. + + .. code-block:: c++ + + class A { + int f() { return 0; }; + }; + int + f(); + int + f() { + return 1; + } + int + LongName::AnotherLongName(); + + * ``RTBS_AllDefinitions`` (in configuration: ``AllDefinitions``) + Always break after the return type of function definitions. + + .. code-block:: c++ + + class A { + int + f() { + return 0; + }; + }; + int f(); + int + f() { + return 1; + } + int + LongName::AnotherLongName(); + + * ``RTBS_TopLevelDefinitions`` (in configuration: ``TopLevelDefinitions``) + Always break after the return type of top-level definitions. + + .. code-block:: c++ + + class A { + int f() { return 0; }; + }; + int f(); + int + f() { + return 1; + } + int + LongName::AnotherLongName(); + + + .. _BreakArrays: **BreakArrays** (``Boolean``) :versionbadge:`clang-format 16` :ref:`¶ ` @@ -3014,6 +2965,65 @@ the configuration (without a prefix: ``Auto``). string x = "veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongString"; +.. _BreakTemplateDeclarations: + +**BreakTemplateDeclarations** (``BreakTemplateDeclarationsStyle``) :versionbadge:`clang-format 19` :ref:`¶ ` + The template declaration breaking style to use. + + Possible values: + + * ``BTDS_Leave`` (in configuration: ``Leave``) + Do not change the line breaking before the declaration. + + .. code-block:: c++ + + template + T foo() { + } + template T foo(int aaaaaaaaaaaaaaaaaaaaa, + int bbbbbbbbbbbbbbbbbbbbb) { + } + + * ``BTDS_No`` (in configuration: ``No``) + Do not force break before declaration. + ``PenaltyBreakTemplateDeclaration`` is taken into account. + + .. code-block:: c++ + + template T foo() { + } + template T foo(int aaaaaaaaaaaaaaaaaaaaa, + int bbbbbbbbbbbbbbbbbbbbb) { + } + + * ``BTDS_MultiLine`` (in configuration: ``MultiLine``) + Force break after template declaration only when the following + declaration spans multiple lines. + + .. code-block:: c++ + + template T foo() { + } + template + T foo(int aaaaaaaaaaaaaaaaaaaaa, + int bbbbbbbbbbbbbbbbbbbbb) { + } + + * ``BTDS_Yes`` (in configuration: ``Yes``) + Always break after template declaration. + + .. code-block:: c++ + + template + T foo() { + } + template + T foo(int aaaaaaaaaaaaaaaaaaaaa, + int bbbbbbbbbbbbbbbbbbbbb) { + } + + + .. _ColumnLimit: **ColumnLimit** (``Unsigned``) :versionbadge:`clang-format 3.7` :ref:`¶ ` @@ -4156,7 +4166,7 @@ the configuration (without a prefix: ``Auto``). .. _MainIncludeChar: -**MainIncludeChar** (``MainIncludeCharDiscriminator``) :versionbadge:`clang-format 18` :ref:`¶ ` +**MainIncludeChar** (``MainIncludeCharDiscriminator``) :versionbadge:`clang-format 19` :ref:`¶ ` When guessing whether a #include is the "main" include, only the include directives that use the specified character are considered. diff --git a/clang/docs/ClangLinkerWrapper.rst b/clang/docs/ClangLinkerWrapper.rst index 6d7770b50e7260014a3fa197d12256232b975c65..3bef558475735115fba43d0290bdd9c0d76dbca7 100644 --- a/clang/docs/ClangLinkerWrapper.rst +++ b/clang/docs/ClangLinkerWrapper.rst @@ -79,6 +79,14 @@ linking is desired, simply do not run the binaries through the ``clang-linker-wrapper``. This will simply append the embedded device code so that it can be linked later. +Matching +======== + +The linker wrapper will link extracted device code that is compatible with each +other. Generally, this requires that the target triple and architecture match. +An exception is made when the architecture is listed as ``generic``, which will +cause it be linked with any other device code with the same target triple. + Example ======= diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index e91156837290f73dbc6ad195c86d8469d2a8dd72..ee1d25396ca865b1126bcb21b18216ac786553b5 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -2764,6 +2764,39 @@ Query for this feature with ``__has_builtin(__builtin_readcyclecounter)``. Note that even if present, its use may depend on run-time privilege or other OS controlled state. +``__builtin_readsteadycounter`` +------------------------------- + +``__builtin_readsteadycounter`` is used to access the fixed frequency counter +register (or a similar steady-rate clock) on those targets that support it. +The function is similar to ``__builtin_readcyclecounter`` above except that the +frequency is fixed, making it suitable for measuring elapsed time. + +**Syntax**: + +.. code-block:: c++ + + __builtin_readsteadycounter() + +**Example of Use**: + +.. code-block:: c++ + + unsigned long long t0 = __builtin_readsteadycounter(); + do_something(); + unsigned long long t1 = __builtin_readsteadycounter(); + unsigned long long secs_to_do_something = (t1 - t0) / tick_rate; + +**Description**: + +The ``__builtin_readsteadycounter()`` builtin returns the frequency counter value. +When not supported by the target, the return value is always zero. This builtin +takes no arguments and produces an unsigned long long result. The builtin does +not guarantee any particular frequency, only that it is stable. Knowledge of the +counter's true frequency will need to be provided by the user. + +Query for this feature with ``__has_builtin(__builtin_readsteadycounter)``. + ``__builtin_dump_struct`` ------------------------- diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 52a48c750fe55bfc4de2ac46b489e81d601da62b..dc2fb3b25e3a54a06fbd7ad9b11d588ca662ac4c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -117,6 +117,9 @@ C23 Feature Support Non-comprehensive list of changes in this release ------------------------------------------------- +- Added ``__builtin_readsteadycounter`` for reading fixed frequency hardware + counters. + New Compiler Flags ------------------ @@ -149,7 +152,12 @@ Improvements to Clang's diagnostics prints. - Clang now diagnoses member template declarations with multiple declarators. -- Clang now diagnoses use of the ``template`` keyword after declarative nested name specifiers. + +- Clang now diagnoses use of the ``template`` keyword after declarative nested + name specifiers. + +- The ``-Wshorten-64-to-32`` diagnostic is now grouped under ``-Wimplicit-int-conversion`` instead + of ``-Wconversion``. Fixes `#69444 `_. Improvements to Clang's time-trace ---------------------------------- @@ -160,6 +168,9 @@ Bug Fixes in This Version a member class template for an implicit instantiation of a class template. - Fixed missing warnings when doing bool-like conversions in C23 (`#79435 `_). +- Clang's ``-Wshadow`` no longer warns when an init-capture is named the same as + a class field unless the lambda can capture this. + Fixes (`#71976 `_) - Clang now accepts qualified partial/explicit specializations of variable templates that are not nominable in the lookup context of the specialization. @@ -177,6 +188,10 @@ Bug Fixes to Attribute Support Bug Fixes to C++ Support ^^^^^^^^^^^^^^^^^^^^^^^^ +- Fix crash when calling the constructor of an invalid class. + Fixes (`#10518 `_), + (`#67914 `_), + and (`#78388 `_) - Fix crash when using lifetimebound attribute in function with trailing return. Fixes (`#73619 `_) - Addressed an issue where constraints involving injected class types are perceived @@ -210,6 +225,14 @@ Bug Fixes to C++ Support Fixes (`#68490 `_) - Fix a crash when trying to call a varargs function that also has an explicit object parameter. Fixes (`#80971 ICE when explicit object parameter be a function parameter pack`) +- Fixed a bug where abbreviated function templates would append their invented template parameters to + an empty template parameter lists. +- Clang now classifies aggregate initialization in C++17 and newer as constant + or non-constant more accurately. Previously, only a subset of the initializer + elements were considered, misclassifying some initializers as constant. Fixes + some of (`#80510 `). +- Clang now ignores top-level cv-qualifiers on function parameters in template partial orderings. + (`#75404 `_) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -235,6 +258,8 @@ X86 Support Arm and AArch64 Support ^^^^^^^^^^^^^^^^^^^^^^^ +- Fixed the incorrect definition of the __ARM_ARCH macro for architectures greater than or equal to v8.1. + Android Support ^^^^^^^^^^^^^^^ @@ -276,6 +301,11 @@ AST Matchers clang-format ------------ +- ``AlwaysBreakTemplateDeclarations`` is deprecated and renamed to + ``BreakTemplateDeclarations``. +- ``AlwaysBreakAfterReturnType`` is deprecated and renamed to + ``BreakAfterReturnType``. + libclang -------- diff --git a/clang/docs/ShadowCallStack.rst b/clang/docs/ShadowCallStack.rst index 6e5192fd672391b87bdc2cc96da556eb25830fe8..d7ece11b3526064e47a7c88f96da6fd8273fb2d4 100644 --- a/clang/docs/ShadowCallStack.rst +++ b/clang/docs/ShadowCallStack.rst @@ -57,19 +57,25 @@ compiled application or the operating system. Integrating the runtime into the operating system should be preferred since otherwise all thread creation and destruction would need to be intercepted by the application. -The instrumentation makes use of the platform register ``x18`` on AArch64 and -``x3`` (``gp``) on RISC-V. For simplicity we will refer to this as the -``SCSReg``. On some platforms, ``SCSReg`` is reserved, and on others, it is -designated as a scratch register. This generally means that any code that may -run on the same thread as code compiled with ShadowCallStack must either target -one of the platforms whose ABI reserves ``SCSReg`` (currently Android, Darwin, -Fuchsia and Windows) or be compiled with a flag to reserve that register (e.g., -``-ffixed-x18``). If absolutely necessary, code compiled without reserving the -register may be run on the same thread as code that uses ShadowCallStack by -saving the register value temporarily on the stack (`example in Android`_) but -this should be done with care since it risks leaking the shadow call stack -address. - +The instrumentation makes use of the platform register ``x18`` on AArch64, +``x3`` (``gp``) on RISC-V with software shadow stack and ``ssp`` on RISC-V with +hardware shadow stack, which needs `Zicfiss`_ and ``-mno-forced-sw-shadow-stack`` +(default option). Note that with ``Zicfiss``_ the RISC-V backend will default to +the hardware based shadow call stack. Users can force the RISC-V backend to +generate the software shadow call stack with ``Zicfiss``_ by passing +``-mforced-sw-shadow-stack``. +For simplicity we will refer to this as the ``SCSReg``. On some platforms, +``SCSReg`` is reserved, and on others, it is designated as a scratch register. +This generally means that any code that may run on the same thread as code +compiled with ShadowCallStack must either target one of the platforms whose ABI +reserves ``SCSReg`` (currently Android, Darwin, Fuchsia and Windows) or be +compiled with a flag to reserve that register (e.g., ``-ffixed-x18``). If +absolutely necessary, code compiled without reserving the register may be run on +the same thread as code that uses ShadowCallStack by saving the register value +temporarily on the stack (`example in Android`_) but this should be done with +care since it risks leaking the shadow call stack address. + +.. _`Zicfiss`: https://github.com/riscv/riscv-cfi/blob/main/cfi_backward.adoc .. _`example in Android`: https://android-review.googlesource.com/c/platform/frameworks/base/+/803717 Because it requires a dedicated register, the ShadowCallStack feature is @@ -151,9 +157,13 @@ Usage To enable ShadowCallStack, just pass the ``-fsanitize=shadow-call-stack`` flag to both compile and link command lines. On aarch64, you also need to pass -``-ffixed-x18`` unless your target already reserves ``x18``. On RISC-V, ``x3`` -(``gp``) is always reserved. It is, however, important to disable GP relaxation -in the linker. This can be done with the ``--no-relax-gp`` flag in GNU ld. +``-ffixed-x18`` unless your target already reserves ``x18``. No additional flags +need to be passed on RISC-V because the software based shadow stack uses +``x3`` (``gp``), which is always reserved, and the hardware based shadow call +stack uses a dedicated register, ``ssp``. +However, it is important to disable GP relaxation in the linker when using the +software based shadow call stack on RISC-V. This can be done with the +``--no-relax-gp`` flag in GNU ld, and is off by default in LLD. Low-level API ------------- diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index bb637cf1b8007bb2ac18d0ce2ab450fee78a997a..510629d8a2d480d4fb765f5a40fe4acc5df0db24 100644 --- a/clang/docs/analyzer/checkers.rst +++ b/clang/docs/analyzer/checkers.rst @@ -1890,28 +1890,6 @@ the locking/unlocking of ``mtx_t`` mutexes. mtx_lock(&mtx1); // warn: This lock has already been acquired } -.. _alpha-core-CallAndMessageUnInitRefArg: - -alpha.core.CallAndMessageUnInitRefArg (C,C++, ObjC) -""""""""""""""""""""""""""""""""""""""""""""""""""" -Check for logical errors for function calls and Objective-C -message expressions (e.g., uninitialized arguments, null function pointers, and pointer to undefined variables). - -.. code-block:: c - - void test(void) { - int t; - int &p = t; - int &s = p; - int &q = s; - foo(q); // warn - } - - void test(void) { - int x; - foo(&x); // warn - } - .. _alpha-core-CastSize: alpha.core.CastSize (C) diff --git a/clang/docs/tools/dump_format_style.py b/clang/docs/tools/dump_format_style.py index e41891f07de2e3291fd7ad9fd4bc6459c28a43ce..af0124b94ecaf1367616908460412640bfe8f193 100755 --- a/clang/docs/tools/dump_format_style.py +++ b/clang/docs/tools/dump_format_style.py @@ -308,6 +308,7 @@ class OptionsReader: enum = None nested_struct = None version = None + deprecated = False for line in self.header: self.lineno += 1 @@ -327,6 +328,8 @@ class OptionsReader: match = re.match(r"/// \\version\s*(?P[0-9.]+)*", line) if match: version = match.group("version") + elif line.startswith("/// @deprecated"): + deprecated = True elif line.startswith("///"): comment += self.__clean_comment_line(line) elif line.startswith("enum"): @@ -345,6 +348,9 @@ class OptionsReader: field_type, field_name = re.match( r"([<>:\w(,\s)]+)\s+(\w+);", line ).groups() + if deprecated: + field_type = "deprecated" + deprecated = False if not version: self.__warning(f"missing version for {field_name}", line) @@ -456,6 +462,7 @@ class OptionsReader: "std::vector", "std::vector", "std::optional", + "deprecated", ]: if option.type in enums: option.enum = enums[option.type] diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 6af41424ba89a147d2576403857268eef63bff5b..3f3620609b6ddc08c88752c0aa744c9f083d01ff 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2145,7 +2145,11 @@ enum CXCursorKind { */ CXCursor_OMPScopeDirective = 306, - CXCursor_LastStmt = CXCursor_OMPScopeDirective, + /** OpenACC Compute Construct. + */ + CXCursor_OpenACCComputeConstruct = 320, + + CXCursor_LastStmt = CXCursor_OpenACCComputeConstruct, /** * Cursor that represents the translation unit itself. diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index 1d116becf06c80553c1d917f08d547d8b3a1fafb..93bb045d6a667046239bccff8deb83dc479d2f6e 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -55,16 +55,20 @@ public: std::string UnavailableMsg; /// Whether this entity is marked unavailable. + LLVM_PREFERRED_TYPE(bool) unsigned Unavailable : 1; /// Whether this entity is marked unavailable in Swift. + LLVM_PREFERRED_TYPE(bool) unsigned UnavailableInSwift : 1; private: /// Whether SwiftPrivate was specified. + LLVM_PREFERRED_TYPE(bool) unsigned SwiftPrivateSpecified : 1; /// Whether this entity is considered "private" to a Swift overlay. + LLVM_PREFERRED_TYPE(bool) unsigned SwiftPrivate : 1; public: @@ -191,18 +195,25 @@ inline bool operator!=(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) { /// Describes API notes data for an Objective-C class or protocol. class ObjCContextInfo : public CommonTypeInfo { /// Whether this class has a default nullability. + LLVM_PREFERRED_TYPE(bool) unsigned HasDefaultNullability : 1; /// The default nullability. + LLVM_PREFERRED_TYPE(NullabilityKind) unsigned DefaultNullability : 2; /// Whether this class has designated initializers recorded. + LLVM_PREFERRED_TYPE(bool) unsigned HasDesignatedInits : 1; + LLVM_PREFERRED_TYPE(bool) unsigned SwiftImportAsNonGenericSpecified : 1; + LLVM_PREFERRED_TYPE(bool) unsigned SwiftImportAsNonGeneric : 1; + LLVM_PREFERRED_TYPE(bool) unsigned SwiftObjCMembersSpecified : 1; + LLVM_PREFERRED_TYPE(bool) unsigned SwiftObjCMembers : 1; public: @@ -298,10 +309,12 @@ inline bool operator!=(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) { /// API notes for a variable/property. class VariableInfo : public CommonEntityInfo { /// Whether this property has been audited for nullability. + LLVM_PREFERRED_TYPE(bool) unsigned NullabilityAudited : 1; /// The kind of nullability for this property. Only valid if the nullability /// has been audited. + LLVM_PREFERRED_TYPE(NullabilityKind) unsigned Nullable : 2; /// The C type of the variable, as a string. @@ -352,7 +365,9 @@ inline bool operator!=(const VariableInfo &LHS, const VariableInfo &RHS) { /// Describes API notes data for an Objective-C property. class ObjCPropertyInfo : public VariableInfo { + LLVM_PREFERRED_TYPE(bool) unsigned SwiftImportAsAccessorsSpecified : 1; + LLVM_PREFERRED_TYPE(bool) unsigned SwiftImportAsAccessors : 1; public: @@ -409,9 +424,11 @@ inline bool operator!=(const ObjCPropertyInfo &LHS, /// Describes a function or method parameter. class ParamInfo : public VariableInfo { /// Whether noescape was specified. + LLVM_PREFERRED_TYPE(bool) unsigned NoEscapeSpecified : 1; /// Whether the this parameter has the 'noescape' attribute. + LLVM_PREFERRED_TYPE(bool) unsigned NoEscape : 1; /// A biased RetainCountConventionKind, where 0 means "unspecified". @@ -488,6 +505,7 @@ public: // unknown nullability. /// Whether the signature has been audited with respect to nullability. + LLVM_PREFERRED_TYPE(bool) unsigned NullabilityAudited : 1; /// Number of types whose nullability is encoded with the NullabilityPayload. @@ -597,9 +615,11 @@ inline bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS) { class ObjCMethodInfo : public FunctionInfo { public: /// Whether this is a designated initializer of its class. + LLVM_PREFERRED_TYPE(bool) unsigned DesignatedInit : 1; /// Whether this is a required initializer. + LLVM_PREFERRED_TYPE(bool) unsigned RequiredInit : 1; ObjCMethodInfo() : DesignatedInit(false), RequiredInit(false) {} @@ -650,7 +670,9 @@ public: /// Describes API notes data for a tag. class TagInfo : public CommonTypeInfo { + LLVM_PREFERRED_TYPE(bool) unsigned HasFlagEnum : 1; + LLVM_PREFERRED_TYPE(bool) unsigned IsFlagEnum : 1; public: diff --git a/clang/include/clang/AST/CommentCommandTraits.h b/clang/include/clang/AST/CommentCommandTraits.h index 83a29a540d42055597967a87c32a0adb419180b3..0c3254d84eb00049ee91ac3427c18788aac8d904 100644 --- a/clang/include/clang/AST/CommentCommandTraits.h +++ b/clang/include/clang/AST/CommentCommandTraits.h @@ -50,52 +50,65 @@ struct CommandInfo { unsigned NumArgs : 4; /// True if this command is a inline command (of any kind). + LLVM_PREFERRED_TYPE(bool) unsigned IsInlineCommand : 1; /// True if this command is a block command (of any kind). + LLVM_PREFERRED_TYPE(bool) unsigned IsBlockCommand : 1; /// True if this command is introducing a brief documentation /// paragraph (\or an alias). + LLVM_PREFERRED_TYPE(bool) unsigned IsBriefCommand : 1; /// True if this command is \\returns or an alias. + LLVM_PREFERRED_TYPE(bool) unsigned IsReturnsCommand : 1; /// True if this command is introducing documentation for a function /// parameter (\\param or an alias). + LLVM_PREFERRED_TYPE(bool) unsigned IsParamCommand : 1; /// True if this command is introducing documentation for /// a template parameter (\\tparam or an alias). + LLVM_PREFERRED_TYPE(bool) unsigned IsTParamCommand : 1; /// True if this command is \\throws or an alias. + LLVM_PREFERRED_TYPE(bool) unsigned IsThrowsCommand : 1; /// True if this command is \\deprecated or an alias. + LLVM_PREFERRED_TYPE(bool) unsigned IsDeprecatedCommand : 1; /// True if this is a \\headerfile-like command. + LLVM_PREFERRED_TYPE(bool) unsigned IsHeaderfileCommand : 1; /// True if we don't want to warn about this command being passed an empty /// paragraph. Meaningful only for block commands. + LLVM_PREFERRED_TYPE(bool) unsigned IsEmptyParagraphAllowed : 1; /// True if this command is a verbatim-like block command. /// /// A verbatim-like block command eats every character (except line starting /// decorations) until matching end command is seen or comment end is hit. + LLVM_PREFERRED_TYPE(bool) unsigned IsVerbatimBlockCommand : 1; /// True if this command is an end command for a verbatim-like block. + LLVM_PREFERRED_TYPE(bool) unsigned IsVerbatimBlockEndCommand : 1; /// True if this command is a verbatim line command. /// /// A verbatim-like line command eats everything until a newline is seen or /// comment end is hit. + LLVM_PREFERRED_TYPE(bool) unsigned IsVerbatimLineCommand : 1; /// True if this command contains a declaration for the entity being @@ -105,20 +118,25 @@ struct CommandInfo { /// \code /// \fn void f(int a); /// \endcode + LLVM_PREFERRED_TYPE(bool) unsigned IsDeclarationCommand : 1; /// True if verbatim-like line command is a function declaration. + LLVM_PREFERRED_TYPE(bool) unsigned IsFunctionDeclarationCommand : 1; /// True if block command is further describing a container API; such /// as \@coclass, \@classdesign, etc. + LLVM_PREFERRED_TYPE(bool) unsigned IsRecordLikeDetailCommand : 1; /// True if block command is a container API; such as \@interface. + LLVM_PREFERRED_TYPE(bool) unsigned IsRecordLikeDeclarationCommand : 1; /// True if this command is unknown. This \c CommandInfo object was /// created during parsing. + LLVM_PREFERRED_TYPE(bool) unsigned IsUnknownCommand : 1; }; diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index f26fb5ad5f133101dce9173233ebc2e31d81540a..61117cc5ce71f9f4422e11a155e945acfd4d56f1 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -2615,10 +2615,18 @@ public: /// the target functionality. bool isTargetMultiVersion() const; + /// True if this function is the default version of a multiversioned dispatch + /// function as a part of the target functionality. + bool isTargetMultiVersionDefault() const; + /// True if this function is a multiversioned dispatch function as a part of /// the target-clones functionality. bool isTargetClonesMultiVersion() const; + /// True if this function is a multiversioned dispatch function as a part of + /// the target-version functionality. + bool isTargetVersionMultiVersion() const; + /// \brief Get the associated-constraints of this function declaration. /// Currently, this will either be a vector of size 1 containing the /// trailing-requires-clause or an empty vector. diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index baf71145d99dc6ab99b3384ce45c249ec68f0311..e3b6a7efb1127af56d594d8299f49a21ed38a43f 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -134,6 +134,7 @@ public: const_iterator end() const { return begin() + NumParams; } unsigned size() const { return NumParams; } + bool empty() const { return NumParams == 0; } ArrayRef asArray() { return llvm::ArrayRef(begin(), end()); } ArrayRef asArray() const { diff --git a/clang/include/clang/AST/RawCommentList.h b/clang/include/clang/AST/RawCommentList.h index 53aae24fa7bbc1b66159162923568bbf141f055b..3e4567b546a71d6bb53de828d8c6aace2ce1c765 100644 --- a/clang/include/clang/AST/RawCommentList.h +++ b/clang/include/clang/AST/RawCommentList.h @@ -175,17 +175,22 @@ private: mutable StringRef RawText; mutable const char *BriefText = nullptr; - mutable bool RawTextValid : 1; ///< True if RawText is valid - mutable bool BriefTextValid : 1; ///< True if BriefText is valid + LLVM_PREFERRED_TYPE(bool) + mutable unsigned RawTextValid : 1; + LLVM_PREFERRED_TYPE(bool) + mutable unsigned BriefTextValid : 1; LLVM_PREFERRED_TYPE(CommentKind) unsigned Kind : 3; /// True if comment is attached to a declaration in ASTContext. - bool IsAttached : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned IsAttached : 1; - bool IsTrailingComment : 1; - bool IsAlmostTrailingComment : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned IsTrailingComment : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned IsAlmostTrailingComment : 1; /// Constructor for AST deserialization. RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment, diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 9da5206a21c34c92ecdd323febabd6544a70736d..5080551ada4fc67b09791a5d2499e5430614d5ef 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -34,6 +34,7 @@ #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" @@ -505,6 +506,9 @@ private: bool VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *Node); bool PostVisitStmt(Stmt *S); + bool TraverseOpenACCConstructStmt(OpenACCConstructStmt *S); + bool + TraverseOpenACCAssociatedStmtConstruct(OpenACCAssociatedStmtConstruct *S); }; template @@ -3910,6 +3914,24 @@ bool RecursiveASTVisitor::VisitOMPXBareClause(OMPXBareClause *C) { return true; } +template +bool RecursiveASTVisitor::TraverseOpenACCConstructStmt( + OpenACCConstructStmt *) { + // TODO OpenACC: When we implement clauses, ensure we traverse them here. + return true; +} + +template +bool RecursiveASTVisitor::TraverseOpenACCAssociatedStmtConstruct( + OpenACCAssociatedStmtConstruct *S) { + TRY_TO(TraverseOpenACCConstructStmt(S)); + TRY_TO(TraverseStmt(S->getAssociatedStmt())); + return true; +} + +DEF_TRAVERSE_STMT(OpenACCComputeConstruct, + { TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); }) + // FIXME: look at the following tricky-seeming exprs to see if we // need to recurse on anything. These are ones that have methods // returning decls or qualtypes or nestednamespecifier -- though I'm diff --git a/clang/include/clang/AST/StmtObjC.h b/clang/include/clang/AST/StmtObjC.h index c46ff4634c825fdfa112e96b5d5eca23b7ed3c70..03bc61f54cdf539db32f1941f06d6d029794c65c 100644 --- a/clang/include/clang/AST/StmtObjC.h +++ b/clang/include/clang/AST/StmtObjC.h @@ -177,7 +177,8 @@ class ObjCAtTryStmt final unsigned NumCatchStmts : 16; // Whether this statement has a \@finally statement. - bool HasFinally : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned HasFinally : 1; /// Retrieve the statements that are stored after this \@try statement. /// diff --git a/clang/include/clang/AST/StmtOpenACC.h b/clang/include/clang/AST/StmtOpenACC.h new file mode 100644 index 0000000000000000000000000000000000000000..9424f4f0807858487a76d92791e098ec5d1d008c --- /dev/null +++ b/clang/include/clang/AST/StmtOpenACC.h @@ -0,0 +1,142 @@ +//===- StmtOpenACC.h - Classes for OpenACC directives ----------*- 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 +// +//===----------------------------------------------------------------------===// +/// \file +/// This file defines OpenACC AST classes for statement-level contructs. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_STMTOPENACC_H +#define LLVM_CLANG_AST_STMTOPENACC_H + +#include "clang/AST/Stmt.h" +#include "clang/Basic/OpenACCKinds.h" +#include "clang/Basic/SourceLocation.h" + +namespace clang { +/// This is the base class for an OpenACC statement-level construct, other +/// construct types are expected to inherit from this. +class OpenACCConstructStmt : public Stmt { + friend class ASTStmtWriter; + friend class ASTStmtReader; + /// The directive kind. Each implementation of this interface should handle + /// specific kinds. + OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid; + /// The location of the directive statement, from the '#' to the last token of + /// the directive. + SourceRange Range; + + // TODO OPENACC: Clauses should probably be collected in this class. + +protected: + OpenACCConstructStmt(StmtClass SC, OpenACCDirectiveKind K, + SourceLocation Start, SourceLocation End) + : Stmt(SC), Kind(K), Range(Start, End) {} + +public: + OpenACCDirectiveKind getDirectiveKind() const { return Kind; } + + static bool classof(const Stmt *S) { + return S->getStmtClass() >= firstOpenACCConstructStmtConstant && + S->getStmtClass() <= lastOpenACCConstructStmtConstant; + } + + SourceLocation getBeginLoc() const { return Range.getBegin(); } + SourceLocation getEndLoc() const { return Range.getEnd(); } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_cast(this)->children(); + } +}; + +/// This is a base class for any OpenACC statement-level constructs that have an +/// associated statement. This class is not intended to be instantiated, but is +/// a convenient place to hold the associated statement. +class OpenACCAssociatedStmtConstruct : public OpenACCConstructStmt { + friend class ASTStmtWriter; + friend class ASTStmtReader; + template friend class RecursiveASTVisitor; + Stmt *AssociatedStmt = nullptr; + +protected: + OpenACCAssociatedStmtConstruct(StmtClass SC, OpenACCDirectiveKind K, + SourceLocation Start, SourceLocation End) + : OpenACCConstructStmt(SC, K, Start, End) {} + + void setAssociatedStmt(Stmt *S) { AssociatedStmt = S; } + Stmt *getAssociatedStmt() { return AssociatedStmt; } + const Stmt *getAssociatedStmt() const { + return const_cast(this) + ->getAssociatedStmt(); + } + +public: + child_range children() { + if (getAssociatedStmt()) + return child_range(&AssociatedStmt, &AssociatedStmt + 1); + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_cast(this)->children(); + } +}; +/// This class represents a compute construct, representing a 'Kind' of +/// `parallel', 'serial', or 'kernel'. These constructs are associated with a +/// 'structured block', defined as: +/// +/// in C or C++, an executable statement, possibly compound, with a single +/// entry at the top and a single exit at the bottom +/// +/// At the moment there is no real motivation to have a different AST node for +/// those three, as they are semantically identical, and have only minor +/// differences in the permitted list of clauses, which can be differentiated by +/// the 'Kind'. +class OpenACCComputeConstruct : public OpenACCAssociatedStmtConstruct { + friend class ASTStmtWriter; + friend class ASTStmtReader; + friend class ASTContext; + OpenACCComputeConstruct() + : OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, + OpenACCDirectiveKind::Invalid, + SourceLocation{}, SourceLocation{}) {} + + OpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation Start, + SourceLocation End) + : OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, K, Start, + End) { + assert((K == OpenACCDirectiveKind::Parallel || + K == OpenACCDirectiveKind::Serial || + K == OpenACCDirectiveKind::Kernels) && + "Only parallel, serial, and kernels constructs should be " + "represented by this type"); + } + + void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); } + +public: + static bool classof(const Stmt *T) { + return T->getStmtClass() == OpenACCComputeConstructClass; + } + + static OpenACCComputeConstruct *CreateEmpty(const ASTContext &C, EmptyShell); + static OpenACCComputeConstruct *Create(const ASTContext &C, + OpenACCDirectiveKind K, + SourceLocation BeginLoc, + SourceLocation EndLoc); + + Stmt *getStructuredBlock() { return getAssociatedStmt(); } + const Stmt *getStructuredBlock() const { + return const_cast(this)->getStructuredBlock(); + } +}; +} // namespace clang +#endif // LLVM_CLANG_AST_STMTOPENACC_H diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h index 62164339153573cb5b98d2860246fff14727cc43..3cb3c1014d73b7526dcfe326f78482ff36e28829 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -2974,6 +2974,7 @@ class OMPAtomicDirective : public OMPExecutableDirective { /// This field is 1 for the first form of the expression and 0 for the /// second. Required for correct codegen of non-associative operations (like /// << or >>). + LLVM_PREFERRED_TYPE(bool) uint8_t IsXLHSInRHSPart : 1; /// Used for 'atomic update' or 'atomic capture' constructs. They may /// have atomic expressions of forms: @@ -2983,9 +2984,11 @@ class OMPAtomicDirective : public OMPExecutableDirective { /// \endcode /// This field is 1 for the first(postfix) form of the expression and 0 /// otherwise. + LLVM_PREFERRED_TYPE(bool) uint8_t IsPostfixUpdate : 1; /// 1 if 'v' is updated only when the condition is false (compare capture /// only). + LLVM_PREFERRED_TYPE(bool) uint8_t IsFailOnly : 1; } Flags; diff --git a/clang/include/clang/AST/StmtVisitor.h b/clang/include/clang/AST/StmtVisitor.h index 3e5155199eace33873ce844adde3006c1046f7ce..990aa2df180d4337abd771a0c8aa7a812c49fca9 100644 --- a/clang/include/clang/AST/StmtVisitor.h +++ b/clang/include/clang/AST/StmtVisitor.h @@ -13,13 +13,14 @@ #ifndef LLVM_CLANG_AST_STMTVISITOR_H #define LLVM_CLANG_AST_STMTVISITOR_H -#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/STLExtras.h" diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index 3c4283f657efa96637b82e41c8ec8737cd26b587..de67f0b5714846f11ff2c5c2f76e8b1d972158f0 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -401,6 +401,7 @@ public: void VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D); void VisitHLSLBufferDecl(const HLSLBufferDecl *D); + void VisitOpenACCConstructStmt(const OpenACCConstructStmt *S); }; } // namespace clang diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h index aca1ad998822c5868be803ccec962c5a9c7d07c2..5d16dcc824c50c581b7a109d8d0fa9f9b3b19886 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h @@ -42,6 +42,43 @@ public: virtual VarGrpRef getGroupOfParms() const =0; }; +// FixitStrategy is a map from variables to the way we plan to emit fixes for +// these variables. It is figured out gradually by trying different fixes +// for different variables depending on gadgets in which these variables +// participate. +class FixitStrategy { +public: + enum class Kind { + Wontfix, // We don't plan to emit a fixit for this variable. + Span, // We recommend replacing the variable with std::span. + Iterator, // We recommend replacing the variable with std::span::iterator. + Array, // We recommend replacing the variable with std::array. + Vector // We recommend replacing the variable with std::vector. + }; + +private: + using MapTy = llvm::DenseMap; + + MapTy Map; + +public: + FixitStrategy() = default; + FixitStrategy(const FixitStrategy &) = delete; // Let's avoid copies. + FixitStrategy &operator=(const FixitStrategy &) = delete; + FixitStrategy(FixitStrategy &&) = default; + FixitStrategy &operator=(FixitStrategy &&) = default; + + void set(const VarDecl *VD, Kind K) { Map[VD] = K; } + + Kind lookup(const VarDecl *VD) const { + auto I = Map.find(VD); + if (I == Map.end()) + return Kind::Wontfix; + + return I->second; + } +}; + /// The interface that lets the caller handle unsafe buffer usage analysis /// results by overriding this class's handle... methods. class UnsafeBufferUsageHandler { @@ -75,9 +112,11 @@ public: /// /// `D` is the declaration of the callable under analysis that owns `Variable` /// and all of its group mates. - virtual void handleUnsafeVariableGroup(const VarDecl *Variable, - const VariableGroupsManager &VarGrpMgr, - FixItList &&Fixes, const Decl *D) = 0; + virtual void + handleUnsafeVariableGroup(const VarDecl *Variable, + const VariableGroupsManager &VarGrpMgr, + FixItList &&Fixes, const Decl *D, + const FixitStrategy &VarTargetTypes) = 0; #ifndef NDEBUG public: diff --git a/clang/include/clang/Analysis/CFG.h b/clang/include/clang/Analysis/CFG.h index 9f776ca6cc260d39d147dec62e772026d95ae2b8..a7ff38c786a8fe6cef196ae60d8fd97a47a56287 100644 --- a/clang/include/clang/Analysis/CFG.h +++ b/clang/include/clang/Analysis/CFG.h @@ -879,6 +879,7 @@ private: /// /// Optimization Note: This bit could be profitably folded with Terminator's /// storage if the memory usage of CFGBlock becomes an issue. + LLVM_PREFERRED_TYPE(bool) unsigned HasNoReturnElement : 1; /// The parent CFG that owns this CFGBlock. @@ -1007,7 +1008,9 @@ public: class FilterOptions { public: + LLVM_PREFERRED_TYPE(bool) unsigned IgnoreNullPredecessors : 1; + LLVM_PREFERRED_TYPE(bool) unsigned IgnoreDefaultsWithCoveredEnums : 1; FilterOptions() diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h index 20e45cc27b01fa8e9eb34f4f93aae70ce0c3d98d..98bdf037880ab09b73f3ca271fe523aeafcdf6e8 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h @@ -100,6 +100,8 @@ public: /// to add to a `RecordStorageLocation` of a given type. /// Typically, this is called from the constructor of a `DataflowAnalysis` /// + /// The field types returned by the callback may not have reference type. + /// /// To maintain the invariant that all `RecordStorageLocation`s of a given /// type have the same fields: /// * The callback must always return the same result for a given type @@ -205,8 +207,17 @@ public: /// type. llvm::StringMap getSyntheticFields(QualType Type) { assert(Type->isRecordType()); - if (SyntheticFieldCallback) - return SyntheticFieldCallback(Type); + if (SyntheticFieldCallback) { + llvm::StringMap Result = SyntheticFieldCallback(Type); + // Synthetic fields are not allowed to have reference type. + assert([&Result] { + for (const auto &Entry : Result) + if (Entry.getValue()->isReferenceType()) + return false; + return true; + }()); + return Result; + } return {}; } diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index 5c737a561a7c1389dd4af549f6f6505f98df488f..0aecc749bf415c3b1700f0560f15b3d4af5078a4 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -681,6 +681,14 @@ private: llvm::DenseSet &Visited, int Depth, int &CreatedValuesCount); + /// Initializes the fields (including synthetic fields) of `Loc` with values, + /// unless values of the field type are not supported or we hit one of the + /// limits at which we stop producing values (controlled by `Visited`, + /// `Depth`, and `CreatedValuesCount`). + void initializeFieldsWithValues(RecordStorageLocation &Loc, + llvm::DenseSet &Visited, int Depth, + int &CreatedValuesCount); + /// Shared implementation of `createObject()` overloads. /// `D` and `InitExpr` may be null. StorageLocation &createObjectInternal(const ValueDecl *D, QualType Ty, diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index b2d5309e142c1ab4d4b679664ce2b300f12d097b..45a29e771f2a21bc7711fa09312de035a4fcfc1f 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3226,8 +3226,8 @@ def TypeVisibility : InheritableAttr { let Args = [EnumArgument<"Visibility", "VisibilityType", ["default", "hidden", "internal", "protected"], ["Default", "Hidden", "Hidden", "Protected"]>]; -// let Subjects = [Tag, ObjCInterface, Namespace]; - let Documentation = [Undocumented]; + // let Subjects = SubjectList<[Tag, ObjCInterface, Namespace], ErrorDiag>; + let Documentation = [TypeVisibilityDocs]; } def VecReturn : InheritableAttr { diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 041786f37fb8a7683983d03a8580baa198a43613..8d369091d21590c022472a0fe083e37d84353558 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2517,6 +2517,14 @@ function it instructs compiler to emit multiple function versions based on priority and target features availability. One of the versions is always ( implicitly or explicitly ) the ``default`` (fallback). Attribute strings can contain dependent features names joined by the "+" sign. + +For targets that support the GNU indirect function (IFUNC) feature, dispatch +is performed by emitting an indirect function that is resolved to the appropriate +target clone at load time. The indirect function is given the name the +multiversioned function would have if it had been declared without the attribute. +For backward compatibility with earlier Clang releases, a function alias with an +``.ifunc`` suffix is also emitted. The ``.ifunc`` suffixed symbol is a deprecated +feature and support for it may be removed in the future. }]; } @@ -5577,6 +5585,25 @@ See :doc:`LTOVisibility`. }]; } +def TypeVisibilityDocs : Documentation { + let Category = DocCatType; + let Content = [{ +The ``type_visibility`` attribute allows the visibility of a type and its vague +linkage objects (vtable, typeinfo, typeinfo name) to be controlled separately from +the visibility of functions and data members of the type. + +For example, this can be used to give default visibility to the typeinfo and the vtable +of a type while still keeping hidden visibility on its member functions and static data +members. + +This attribute can only be applied to types and namespaces. + +If both ``visibility`` and ``type_visibility`` are applied to a type or a namespace, the +visibility specified with the ``type_visibility`` attribute overrides the visibility +provided with the regular ``visibility`` attribute. + }]; +} + def RenderScriptKernelAttributeDocs : Documentation { let Category = DocCatFunction; let Content = [{ diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 31a2bdeb2d3e5e382115c089c31c8b1101b36836..193d5851f9f29f0ced3f5b6c37cd82946f9677cc 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -1110,6 +1110,12 @@ def ReadCycleCounter : Builtin { let Prototype = "unsigned long long int()"; } +def ReadSteadyCounter : Builtin { + let Spellings = ["__builtin_readsteadycounter"]; + let Attributes = [NoThrow]; + let Prototype = "unsigned long long int()"; +} + def Trap : Builtin { let Spellings = ["__builtin_trap"]; let Attributes = [NoThrow, NoReturn]; diff --git a/clang/include/clang/Basic/BuiltinsBase.td b/clang/include/clang/Basic/BuiltinsBase.td index b65b41be03265561b7ff88b5fcb974a5c62db05a..bfccff5600ddb378347a0f07de23b812a36e8a2e 100644 --- a/clang/include/clang/Basic/BuiltinsBase.td +++ b/clang/include/clang/Basic/BuiltinsBase.td @@ -87,7 +87,9 @@ class CustomEntry { } class AtomicBuiltin : Builtin; -class TargetBuiltin : Builtin; +class TargetBuiltin : Builtin { + string Features = ""; +} class LibBuiltin : Builtin { string Header = header; diff --git a/clang/include/clang/Basic/BuiltinsNVPTX.def b/clang/include/clang/Basic/BuiltinsNVPTX.def index 7819e71d7fe2aaf97383be7f4ab171ef8c11c647..8d3c5e69d55cf492f27e65fee1aa3a6a9bc9d011 100644 --- a/clang/include/clang/Basic/BuiltinsNVPTX.def +++ b/clang/include/clang/Basic/BuiltinsNVPTX.def @@ -159,6 +159,7 @@ BUILTIN(__nvvm_read_ptx_sreg_pm3, "i", "n") BUILTIN(__nvvm_prmt, "UiUiUiUi", "") BUILTIN(__nvvm_exit, "v", "r") +BUILTIN(__nvvm_reflect, "UicC*", "r") TARGET_BUILTIN(__nvvm_nanosleep, "vUi", "n", AND(SM_70, PTX63)) // Min Max diff --git a/clang/include/clang/Basic/BuiltinsRISCV.def b/clang/include/clang/Basic/BuiltinsRISCV.def deleted file mode 100644 index 1528b18c82eade8110af23b45297d49b49db8f32..0000000000000000000000000000000000000000 --- a/clang/include/clang/Basic/BuiltinsRISCV.def +++ /dev/null @@ -1,93 +0,0 @@ -//==- BuiltinsRISCV.def - RISC-V Builtin function database -------*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the RISC-V-specific builtin function database. Users of -// this file must define the BUILTIN macro to make use of this information. -// -//===----------------------------------------------------------------------===// - -#if defined(BUILTIN) && !defined(TARGET_BUILTIN) -# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS) -#endif - -// Zbb extension -TARGET_BUILTIN(__builtin_riscv_orc_b_32, "UiUi", "nc", "zbb") -TARGET_BUILTIN(__builtin_riscv_orc_b_64, "UWiUWi", "nc", "zbb,64bit") -TARGET_BUILTIN(__builtin_riscv_clz_32, "UiUi", "nc", "zbb|xtheadbb") -TARGET_BUILTIN(__builtin_riscv_clz_64, "UiUWi", "nc", "zbb|xtheadbb,64bit") -TARGET_BUILTIN(__builtin_riscv_ctz_32, "UiUi", "nc", "zbb") -TARGET_BUILTIN(__builtin_riscv_ctz_64, "UiUWi", "nc", "zbb,64bit") - -// Zbc or Zbkc extension -TARGET_BUILTIN(__builtin_riscv_clmul_32, "UiUiUi", "nc", "zbc|zbkc") -TARGET_BUILTIN(__builtin_riscv_clmul_64, "UWiUWiUWi", "nc", "zbc|zbkc,64bit") -TARGET_BUILTIN(__builtin_riscv_clmulh_32, "UiUiUi", "nc", "zbc|zbkc,32bit") -TARGET_BUILTIN(__builtin_riscv_clmulh_64, "UWiUWiUWi", "nc", "zbc|zbkc,64bit") -TARGET_BUILTIN(__builtin_riscv_clmulr_32, "UiUiUi", "nc", "zbc,32bit") -TARGET_BUILTIN(__builtin_riscv_clmulr_64, "UWiUWiUWi", "nc", "zbc,64bit") - -// Zbkx -TARGET_BUILTIN(__builtin_riscv_xperm4_32, "UiUiUi", "nc", "zbkx,32bit") -TARGET_BUILTIN(__builtin_riscv_xperm4_64, "UWiUWiUWi", "nc", "zbkx,64bit") -TARGET_BUILTIN(__builtin_riscv_xperm8_32, "UiUiUi", "nc", "zbkx,32bit") -TARGET_BUILTIN(__builtin_riscv_xperm8_64, "UWiUWiUWi", "nc", "zbkx,64bit") - -// Zbkb extension -TARGET_BUILTIN(__builtin_riscv_brev8_32, "UiUi", "nc", "zbkb") -TARGET_BUILTIN(__builtin_riscv_brev8_64, "UWiUWi", "nc", "zbkb,64bit") -TARGET_BUILTIN(__builtin_riscv_zip_32, "UiUi", "nc", "zbkb,32bit") -TARGET_BUILTIN(__builtin_riscv_unzip_32, "UiUi", "nc", "zbkb,32bit") - -// Zknd extension -TARGET_BUILTIN(__builtin_riscv_aes32dsi, "UiUiUiIUi", "nc", "zknd,32bit") -TARGET_BUILTIN(__builtin_riscv_aes32dsmi, "UiUiUiIUi", "nc", "zknd,32bit") -TARGET_BUILTIN(__builtin_riscv_aes64ds, "UWiUWiUWi", "nc", "zknd,64bit") -TARGET_BUILTIN(__builtin_riscv_aes64dsm, "UWiUWiUWi", "nc", "zknd,64bit") -TARGET_BUILTIN(__builtin_riscv_aes64im, "UWiUWi", "nc", "zknd,64bit") - -// Zknd & Zkne -TARGET_BUILTIN(__builtin_riscv_aes64ks1i, "UWiUWiIUi", "nc", "zknd|zkne,64bit") -TARGET_BUILTIN(__builtin_riscv_aes64ks2, "UWiUWiUWi", "nc", "zknd|zkne,64bit") - -// Zkne extension -TARGET_BUILTIN(__builtin_riscv_aes32esi, "UiUiUiIUi", "nc", "zkne,32bit") -TARGET_BUILTIN(__builtin_riscv_aes32esmi, "UiUiUiIUi", "nc", "zkne,32bit") -TARGET_BUILTIN(__builtin_riscv_aes64es, "UWiUWiUWi", "nc", "zkne,64bit") -TARGET_BUILTIN(__builtin_riscv_aes64esm, "UWiUWiUWi", "nc", "zkne,64bit") - -// Zknh extension -TARGET_BUILTIN(__builtin_riscv_sha256sig0, "UiUi", "nc", "zknh") -TARGET_BUILTIN(__builtin_riscv_sha256sig1, "UiUi", "nc", "zknh") -TARGET_BUILTIN(__builtin_riscv_sha256sum0, "UiUi", "nc", "zknh") -TARGET_BUILTIN(__builtin_riscv_sha256sum1, "UiUi", "nc", "zknh") - -TARGET_BUILTIN(__builtin_riscv_sha512sig0h, "UiUiUi", "nc", "zknh,32bit") -TARGET_BUILTIN(__builtin_riscv_sha512sig0l, "UiUiUi", "nc", "zknh,32bit") -TARGET_BUILTIN(__builtin_riscv_sha512sig1h, "UiUiUi", "nc", "zknh,32bit") -TARGET_BUILTIN(__builtin_riscv_sha512sig1l, "UiUiUi", "nc", "zknh,32bit") -TARGET_BUILTIN(__builtin_riscv_sha512sum0r, "UiUiUi", "nc", "zknh,32bit") -TARGET_BUILTIN(__builtin_riscv_sha512sum1r, "UiUiUi", "nc", "zknh,32bit") -TARGET_BUILTIN(__builtin_riscv_sha512sig0, "UWiUWi", "nc", "zknh,64bit") -TARGET_BUILTIN(__builtin_riscv_sha512sig1, "UWiUWi", "nc", "zknh,64bit") -TARGET_BUILTIN(__builtin_riscv_sha512sum0, "UWiUWi", "nc", "zknh,64bit") -TARGET_BUILTIN(__builtin_riscv_sha512sum1, "UWiUWi", "nc", "zknh,64bit") - -// Zksed extension -TARGET_BUILTIN(__builtin_riscv_sm4ed, "UiUiUiIUi", "nc", "zksed") -TARGET_BUILTIN(__builtin_riscv_sm4ks, "UiUiUiIUi", "nc", "zksed") - -// Zksh extension -TARGET_BUILTIN(__builtin_riscv_sm3p0, "UiUi", "nc", "zksh") -TARGET_BUILTIN(__builtin_riscv_sm3p1, "UiUi", "nc", "zksh") - -// Zihintntl extension -TARGET_BUILTIN(__builtin_riscv_ntl_load, "v.", "t", "zihintntl") -TARGET_BUILTIN(__builtin_riscv_ntl_store, "v.", "t", "zihintntl") - -#undef BUILTIN -#undef TARGET_BUILTIN diff --git a/clang/include/clang/Basic/BuiltinsRISCV.td b/clang/include/clang/Basic/BuiltinsRISCV.td new file mode 100644 index 0000000000000000000000000000000000000000..4cc89a8a9d8af267a5b79c094c69553e542015df --- /dev/null +++ b/clang/include/clang/Basic/BuiltinsRISCV.td @@ -0,0 +1,148 @@ +//==- BuiltinsRISCV.td - RISC-V Builtin function database ---*- tablegen -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the RISC-V-specific builtin function database. +// +//===----------------------------------------------------------------------===// + +include "clang/Basic/BuiltinsBase.td" + +class RISCVBuiltin : TargetBuiltin { + let Spellings = ["__builtin_riscv_" # NAME]; + let Prototype = prototype; + let Features = features; +} + +let Attributes = [NoThrow, Const] in { +//===----------------------------------------------------------------------===// +// Zbb extension. +//===----------------------------------------------------------------------===// +def orc_b_32 : RISCVBuiltin<"unsigned int(unsigned int)", "zbb">; +def orc_b_64 : RISCVBuiltin<"uint64_t(uint64_t)", "zbb,64bit">; +def clz_32 : RISCVBuiltin<"unsigned int(unsigned int)", "zbb|xtheadbb">; +def clz_64 : RISCVBuiltin<"unsigned int(uint64_t)", "zbb|xtheadbb,64bit">; +def ctz_32 : RISCVBuiltin<"unsigned int(unsigned int)", "zbb">; +def ctz_64 : RISCVBuiltin<"unsigned int(uint64_t)", "zbb,64bit">; + +//===----------------------------------------------------------------------===// +// Zbc or Zbkc extension. +//===----------------------------------------------------------------------===// +def clmul_32 : RISCVBuiltin<"unsigned int(unsigned int, unsigned int)", "zbc|zbkc">; +def clmul_64 : RISCVBuiltin<"uint64_t(uint64_t, uint64_t)", "zbc|zbkc,64bit">; +def clmulh_32 : RISCVBuiltin<"unsigned int(unsigned int, unsigned int)", "zbc|zbkc,32bit">; +def clmulh_64 : RISCVBuiltin<"uint64_t(uint64_t, uint64_t)", "zbc|zbkc,64bit">; +def clmulr_32 : RISCVBuiltin<"unsigned int(unsigned int, unsigned int)", "zbc,32bit">; +def clmulr_64 : RISCVBuiltin<"uint64_t(uint64_t, uint64_t)", "zbc,64bit">; + +//===----------------------------------------------------------------------===// +// Zbkx extension. +//===----------------------------------------------------------------------===// +let Features = "zbkx,32bit" in { +def xperm4_32 : RISCVBuiltin<"unsigned int(unsigned int, unsigned int)">; +def xperm8_32 : RISCVBuiltin<"unsigned int(unsigned int, unsigned int)">; +} // Features = "zbkx,32bit" + +let Features = "zbkx,64bit" in { +def xperm4_64 : RISCVBuiltin<"uint64_t(uint64_t, uint64_t)">; +def xperm8_64 : RISCVBuiltin<"uint64_t(uint64_t, uint64_t)">; +} // Features = "zbkx,64bit" + +//===----------------------------------------------------------------------===// +// Zbkb extension. +//===----------------------------------------------------------------------===// +def brev8_32 : RISCVBuiltin<"unsigned int(unsigned int)", "zbkb">; +def brev8_64 : RISCVBuiltin<"uint64_t(uint64_t)", "zbkb,64bit">; +def zip_32 : RISCVBuiltin<"unsigned int(unsigned int)", "zbkb,32bit">; +def unzip_32 : RISCVBuiltin<"unsigned int(unsigned int)", "zbkb,32bit">; + +//===----------------------------------------------------------------------===// +// Zknd extension. +//===----------------------------------------------------------------------===// +let Features = "zknd,32bit" in { +def aes32dsi : RISCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)">; +def aes32dsmi : RISCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)">; +} // Features = "zknd,32bit" + +let Features = "zknd,64bit" in { +def aes64ds : RISCVBuiltin<"uint64_t(uint64_t, uint64_t)">; +def aes64dsm : RISCVBuiltin<"uint64_t(uint64_t, uint64_t)">; +def aes64im : RISCVBuiltin<"uint64_t(uint64_t)">; +} // Features = "zknd,64bit" + +//===----------------------------------------------------------------------===// +// Zknd & Zkne extension. +//===----------------------------------------------------------------------===// +let Features = "zknd|zkne,64bit" in { +def aes64ks1i : RISCVBuiltin<"uint64_t(uint64_t, _Constant unsigned int)">; +def aes64ks2 : RISCVBuiltin<"uint64_t(uint64_t, uint64_t)">; +} // Features = "zknd|zkne,64bit" + +//===----------------------------------------------------------------------===// +// Zkne extension. +//===----------------------------------------------------------------------===// +let Features = "zkne,32bit" in { +def aes32esi : RISCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)">; +def aes32esmi : RISCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)">; +} // Features = "zkne,32bit" + +let Features = "zkne,64bit" in { +def aes64es : RISCVBuiltin<"uint64_t(uint64_t, uint64_t)">; +def aes64esm : RISCVBuiltin<"uint64_t(uint64_t, uint64_t)">; +} // Features = "zkne,64bit" + +//===----------------------------------------------------------------------===// +// Zknh extension. +//===----------------------------------------------------------------------===// +let Features = "zknh" in { +def sha256sig0 : RISCVBuiltin<"unsigned int(unsigned int)">; +def sha256sig1 : RISCVBuiltin<"unsigned int(unsigned int)">; +def sha256sum0 : RISCVBuiltin<"unsigned int(unsigned int)">; +def sha256sum1 : RISCVBuiltin<"unsigned int(unsigned int)">; +} // Features = "zknh" + +let Features = "zknh,32bit" in { +def sha512sig0h : RISCVBuiltin<"unsigned int(unsigned int, unsigned int)">; +def sha512sig0l : RISCVBuiltin<"unsigned int(unsigned int, unsigned int)">; +def sha512sig1h : RISCVBuiltin<"unsigned int(unsigned int, unsigned int)">; +def sha512sig1l : RISCVBuiltin<"unsigned int(unsigned int, unsigned int)">; +def sha512sum0r : RISCVBuiltin<"unsigned int(unsigned int, unsigned int)">; +def sha512sum1r : RISCVBuiltin<"unsigned int(unsigned int, unsigned int)">; +} // Features = "zknh,32bit" + +let Features = "zknh,64bit" in { +def sha512sig0 : RISCVBuiltin<"uint64_t(uint64_t)">; +def sha512sig1 : RISCVBuiltin<"uint64_t(uint64_t)">; +def sha512sum0 : RISCVBuiltin<"uint64_t(uint64_t)">; +def sha512sum1 : RISCVBuiltin<"uint64_t(uint64_t)">; +} // Features = "zknh,64bit" + +//===----------------------------------------------------------------------===// +// Zksed extension. +//===----------------------------------------------------------------------===// +let Features = "zksed" in { +def sm4ed : RISCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int )">; +def sm4ks : RISCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)">; +} // Features = "zksed" + +//===----------------------------------------------------------------------===// +// Zksh extension. +//===----------------------------------------------------------------------===// +let Features = "zksh" in { +def sm3p0 : RISCVBuiltin<"unsigned int(unsigned int)">; +def sm3p1 : RISCVBuiltin<"unsigned int(unsigned int)">; +} // Features = "zksh" + +} // Attributes = [Const, NoThrow] + +//===----------------------------------------------------------------------===// +// Zihintntl extension. +//===----------------------------------------------------------------------===// +let Features = "zihintntl", Attributes = [CustomTypeChecking] in { +def ntl_load : RISCVBuiltin<"void(...)">; +def ntl_store : RISCVBuiltin<"void(...)">; +} // Features = "zihintntl", Attributes = [CustomTypeChecking] diff --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt index 9689a0f48c3ca3fc3850a473829c20713afd7781..7785fb430c069ba7d065d52ad9e9bdc1a3d0c4a4 100644 --- a/clang/include/clang/Basic/CMakeLists.txt +++ b/clang/include/clang/Basic/CMakeLists.txt @@ -65,6 +65,10 @@ clang_tablegen(BuiltinsBPF.inc -gen-clang-builtins SOURCE BuiltinsBPF.td TARGET ClangBuiltinsBPF) +clang_tablegen(BuiltinsRISCV.inc -gen-clang-builtins + SOURCE BuiltinsRISCV.td + TARGET ClangBuiltinsRISCV) + # ARM NEON and MVE clang_tablegen(arm_neon.inc -gen-arm-neon-sema SOURCE arm_neon.td diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 6765721ae7002c19ce7aa4206172cb244e25e863..975eca0ad9b64264392c94c17b8a8c16c4f8cc52 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -108,8 +108,10 @@ def EnumConversion : DiagGroup<"enum-conversion", EnumCompareConditional]>; def ObjCSignedCharBoolImplicitIntConversion : DiagGroup<"objc-signed-char-bool-implicit-int-conversion">; +def Shorten64To32 : DiagGroup<"shorten-64-to-32">; def ImplicitIntConversion : DiagGroup<"implicit-int-conversion", - [ObjCSignedCharBoolImplicitIntConversion]>; + [Shorten64To32, + ObjCSignedCharBoolImplicitIntConversion]>; def ImplicitConstIntFloatConversion : DiagGroup<"implicit-const-int-float-conversion">; def ImplicitIntFloatConversion : DiagGroup<"implicit-int-float-conversion", [ImplicitConstIntFloatConversion]>; @@ -631,7 +633,6 @@ def Shadow : DiagGroup<"shadow", [ShadowFieldInConstructorModified, def ShadowAll : DiagGroup<"shadow-all", [Shadow, ShadowFieldInConstructor, ShadowUncapturedLocal, ShadowField]>; -def Shorten64To32 : DiagGroup<"shorten-64-to-32">; def : DiagGroup<"sign-promo">; def SignCompare : DiagGroup<"sign-compare">; def SwitchDefault : DiagGroup<"switch-default">; @@ -942,7 +943,6 @@ def Conversion : DiagGroup<"conversion", EnumConversion, BitFieldEnumConversion, FloatConversion, - Shorten64To32, IntConversion, ImplicitIntConversion, ImplicitFloatConversion, diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b4dc4feee8e63afafb8877d79a62a642cc99820f..754733a6c5fffd5cc67aac83f9a102ce7906ef75 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3728,6 +3728,8 @@ def err_sme_definition_using_zt0_in_non_sme2_target : Error< "function using ZT0 state requires 'sme2'">; def err_conflicting_attributes_arm_state : Error< "conflicting attributes for state '%0'">; +def err_sme_streaming_cannot_be_multiversioned : Error< + "streaming function cannot be multi-versioned">; def err_unknown_arm_state : Error< "unknown state '%0'">; def err_missing_arm_state : Error< @@ -12126,9 +12128,9 @@ def warn_unsafe_buffer_operation : Warning< def note_unsafe_buffer_operation : Note< "used%select{| in pointer arithmetic| in buffer access}0 here">; def note_unsafe_buffer_variable_fixit_group : Note< - "change type of %0 to '%select{std::span|std::array|std::span::iterator}1' to preserve bounds information%select{|, and change %2 to '%select{std::span|std::array|std::span::iterator}1' to propagate bounds information between them}3">; + "change type of %0 to '%select{std::span' to preserve bounds information|std::array' to label it for hardening|std::span::iterator' to preserve bounds information}1%select{|, and change %2 to '%select{std::span|std::array|std::span::iterator}1' to propagate bounds information between them}3">; def note_unsafe_buffer_variable_fixit_together : Note< - "change type of %0 to '%select{std::span|std::array|std::span::iterator}1' to preserve bounds information" + "change type of %0 to '%select{std::span' to preserve bounds information|std::array' to label it for hardening|std::span::iterator' to preserve bounds information}1" "%select{|, and change %2 to safe types to make function %4 bounds-safe}3">; def note_safe_buffer_usage_suggestions_disabled : Note< "pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions">; diff --git a/clang/include/clang/Basic/IdentifierTable.h b/clang/include/clang/Basic/IdentifierTable.h index 1ac182d4fce26f65f2179aaee96b4706bbb696ea..fa8969eb73ddbf1b093a88d5a433688f21c1e4ab 100644 --- a/clang/include/clang/Basic/IdentifierTable.h +++ b/clang/include/clang/Basic/IdentifierTable.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H #define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H +#include "clang/Basic/Builtins.h" #include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/TokenKinds.h" @@ -86,19 +87,26 @@ enum { IdentifierInfoAlignment = 8 }; static constexpr int ObjCOrBuiltinIDBits = 16; /// The "layout" of ObjCOrBuiltinID is: -/// - The first value (0) represents "not a special identifier". -/// - The next (NUM_OBJC_KEYWORDS - 1) values represent ObjCKeywordKinds (not -/// including objc_not_keyword). -/// - The next (NUM_INTERESTING_IDENTIFIERS - 1) values represent -/// InterestingIdentifierKinds (not including not_interesting). -/// - The rest of the values represent builtin IDs (not including NotBuiltin). -static constexpr int FirstObjCKeywordID = 1; -static constexpr int LastObjCKeywordID = - FirstObjCKeywordID + tok::NUM_OBJC_KEYWORDS - 2; -static constexpr int FirstInterestingIdentifierID = LastObjCKeywordID + 1; -static constexpr int LastInterestingIdentifierID = - FirstInterestingIdentifierID + tok::NUM_INTERESTING_IDENTIFIERS - 2; -static constexpr int FirstBuiltinID = LastInterestingIdentifierID + 1; +/// - ObjCKeywordKind enumerators +/// - InterestingIdentifierKind enumerators +/// - Builtin::ID enumerators +/// - NonSpecialIdentifier +enum class ObjCKeywordOrInterestingOrBuiltin { +#define OBJC_AT_KEYWORD(X) objc_##X, +#include "clang/Basic/TokenKinds.def" + NUM_OBJC_KEYWORDS, + +#define INTERESTING_IDENTIFIER(X) X, +#include "clang/Basic/TokenKinds.def" + NUM_OBJC_KEYWORDS_AND_INTERESTING_IDENTIFIERS, + + NotBuiltin, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/Builtins.inc" + FirstTSBuiltin, + + NonSpecialIdentifier = 65534 +}; /// One of these records is kept for each identifier that /// is lexed. This contains information about whether the token was \#define'd, @@ -113,9 +121,7 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo { LLVM_PREFERRED_TYPE(tok::TokenKind) unsigned TokenID : 9; - // ObjC keyword ('protocol' in '@protocol') or builtin (__builtin_inf). - // First NUM_OBJC_KEYWORDS values are for Objective-C, - // the remaining values are for builtins. + LLVM_PREFERRED_TYPE(ObjCKeywordOrInterestingOrBuiltin) unsigned ObjCOrBuiltinID : ObjCOrBuiltinIDBits; // True if there is a #define for this. @@ -198,13 +204,16 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo { llvm::StringMapEntry *Entry = nullptr; IdentifierInfo() - : TokenID(tok::identifier), ObjCOrBuiltinID(0), HasMacro(false), - HadMacro(false), IsExtension(false), IsFutureCompatKeyword(false), - IsPoisoned(false), IsCPPOperatorKeyword(false), - NeedsHandleIdentifier(false), IsFromAST(false), ChangedAfterLoad(false), - FEChangedAfterLoad(false), RevertedTokenID(false), OutOfDate(false), - IsModulesImport(false), IsMangledOpenMPVariantName(false), - IsDeprecatedMacro(false), IsRestrictExpansion(false), IsFinal(false) {} + : TokenID(tok::identifier), + ObjCOrBuiltinID(llvm::to_underlying( + ObjCKeywordOrInterestingOrBuiltin::NonSpecialIdentifier)), + HasMacro(false), HadMacro(false), IsExtension(false), + IsFutureCompatKeyword(false), IsPoisoned(false), + IsCPPOperatorKeyword(false), NeedsHandleIdentifier(false), + IsFromAST(false), ChangedAfterLoad(false), FEChangedAfterLoad(false), + RevertedTokenID(false), OutOfDate(false), IsModulesImport(false), + IsMangledOpenMPVariantName(false), IsDeprecatedMacro(false), + IsRestrictExpansion(false), IsFinal(false) {} public: IdentifierInfo(const IdentifierInfo &) = delete; @@ -332,42 +341,66 @@ public: /// /// For example, 'class' will return tok::objc_class if ObjC is enabled. tok::ObjCKeywordKind getObjCKeywordID() const { - static_assert(FirstObjCKeywordID == 1, - "hard-coding this assumption to simplify code"); - if (ObjCOrBuiltinID <= LastObjCKeywordID) - return tok::ObjCKeywordKind(ObjCOrBuiltinID); - else - return tok::objc_not_keyword; + assert(0 == llvm::to_underlying( + ObjCKeywordOrInterestingOrBuiltin::objc_not_keyword)); + auto Value = + static_cast(ObjCOrBuiltinID); + if (Value < ObjCKeywordOrInterestingOrBuiltin::NUM_OBJC_KEYWORDS) + return static_cast(ObjCOrBuiltinID); + return tok::objc_not_keyword; + } + void setObjCKeywordID(tok::ObjCKeywordKind ID) { + assert(0 == llvm::to_underlying( + ObjCKeywordOrInterestingOrBuiltin::objc_not_keyword)); + ObjCOrBuiltinID = ID; + assert(getObjCKeywordID() == ID && "ID too large for field!"); } - void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; } /// Return a value indicating whether this is a builtin function. - /// - /// 0 is not-built-in. 1+ are specific builtin functions. unsigned getBuiltinID() const { - if (ObjCOrBuiltinID >= FirstBuiltinID) - return 1 + (ObjCOrBuiltinID - FirstBuiltinID); - else - return 0; + auto Value = + static_cast(ObjCOrBuiltinID); + if (Value > ObjCKeywordOrInterestingOrBuiltin:: + NUM_OBJC_KEYWORDS_AND_INTERESTING_IDENTIFIERS && + Value != ObjCKeywordOrInterestingOrBuiltin::NonSpecialIdentifier) { + auto FirstBuiltin = + llvm::to_underlying(ObjCKeywordOrInterestingOrBuiltin::NotBuiltin); + return static_cast(ObjCOrBuiltinID - FirstBuiltin); + } + return Builtin::ID::NotBuiltin; } void setBuiltinID(unsigned ID) { - assert(ID != 0); - ObjCOrBuiltinID = FirstBuiltinID + (ID - 1); + assert(ID != Builtin::ID::NotBuiltin); + auto FirstBuiltin = + llvm::to_underlying(ObjCKeywordOrInterestingOrBuiltin::NotBuiltin); + ObjCOrBuiltinID = ID + FirstBuiltin; assert(getBuiltinID() == ID && "ID too large for field!"); } - void clearBuiltinID() { ObjCOrBuiltinID = 0; } + void clearBuiltinID() { + ObjCOrBuiltinID = llvm::to_underlying( + ObjCKeywordOrInterestingOrBuiltin::NonSpecialIdentifier); + } tok::InterestingIdentifierKind getInterestingIdentifierID() const { - if (ObjCOrBuiltinID >= FirstInterestingIdentifierID && - ObjCOrBuiltinID <= LastInterestingIdentifierID) - return tok::InterestingIdentifierKind( - 1 + (ObjCOrBuiltinID - FirstInterestingIdentifierID)); - else - return tok::not_interesting; + auto Value = + static_cast(ObjCOrBuiltinID); + if (Value > ObjCKeywordOrInterestingOrBuiltin::NUM_OBJC_KEYWORDS && + Value < ObjCKeywordOrInterestingOrBuiltin:: + NUM_OBJC_KEYWORDS_AND_INTERESTING_IDENTIFIERS) { + auto FirstInterestingIdentifier = + 1 + llvm::to_underlying( + ObjCKeywordOrInterestingOrBuiltin::NUM_OBJC_KEYWORDS); + return static_cast( + ObjCOrBuiltinID - FirstInterestingIdentifier); + } + return tok::not_interesting; } void setInterestingIdentifierID(unsigned ID) { assert(ID != tok::not_interesting); - ObjCOrBuiltinID = FirstInterestingIdentifierID + (ID - 1); + auto FirstInterestingIdentifier = + 1 + llvm::to_underlying( + ObjCKeywordOrInterestingOrBuiltin::NUM_OBJC_KEYWORDS); + ObjCOrBuiltinID = ID + FirstInterestingIdentifier; assert(getInterestingIdentifierID() == ID && "ID too large for field!"); } diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index c1cc5548ef10c0fcf1467109e31c916510b52900..862952d336ef3176fb6c814de78a376baa752f3e 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -30,27 +30,6 @@ namespace clang { -/// Bitfields of LangOptions, split out from LangOptions in order to ensure that -/// this large collection of bitfields is a trivial class type. -class LangOptionsBase { - friend class CompilerInvocation; - friend class CompilerInvocationBase; - -public: - // Define simple language options (with no accessors). -#define LANGOPT(Name, Bits, Default, Description) unsigned Name : Bits; -#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) -#include "clang/Basic/LangOptions.def" - -protected: - // Define language options of enumeration type. These are private, and will - // have accessors (below). -#define LANGOPT(Name, Bits, Default, Description) -#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ - unsigned Name : Bits; -#include "clang/Basic/LangOptions.def" -}; - /// In the Microsoft ABI, this controls the placement of virtual displacement /// members used to implement virtual inheritance. enum class MSVtorDispMode { Never, ForVBaseOverride, ForVFTable }; @@ -78,9 +57,12 @@ enum class ShaderStage { Invalid, }; -/// Keeps track of the various options that can be -/// enabled, which controls the dialect of C or C++ that is accepted. -class LangOptions : public LangOptionsBase { +/// Bitfields of LangOptions, split out from LangOptions in order to ensure that +/// this large collection of bitfields is a trivial class type. +class LangOptionsBase { + friend class CompilerInvocation; + friend class CompilerInvocationBase; + public: using Visibility = clang::Visibility; using RoundingMode = llvm::RoundingMode; @@ -416,6 +398,24 @@ public: enum ComplexRangeKind { CX_Full, CX_Limited, CX_Fortran, CX_None }; + // Define simple language options (with no accessors). +#define LANGOPT(Name, Bits, Default, Description) unsigned Name : Bits; +#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) +#include "clang/Basic/LangOptions.def" + +protected: + // Define language options of enumeration type. These are private, and will + // have accessors (below). +#define LANGOPT(Name, Bits, Default, Description) +#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ + LLVM_PREFERRED_TYPE(Type) \ + unsigned Name : Bits; +#include "clang/Basic/LangOptions.def" +}; + +/// Keeps track of the various options that can be +/// enabled, which controls the dialect of C or C++ that is accepted. +class LangOptions : public LangOptionsBase { public: /// The used language standard. LangStandard::Kind LangStd; diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index 62786e3ac865e640960279afeda93e333fab596a..30ec9c99315092965b0997eb9b6b41c3e52fb6e1 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -118,7 +118,7 @@ public: /// of header files. ModuleMapModule, - /// This is a C++ 20 header unit. + /// This is a C++20 header unit. ModuleHeaderUnit, /// This is a C++20 module interface unit. @@ -127,10 +127,10 @@ public: /// This is a C++20 module implementation unit. ModuleImplementationUnit, - /// This is a C++ 20 module partition interface. + /// This is a C++20 module partition interface. ModulePartitionInterface, - /// This is a C++ 20 module partition implementation. + /// This is a C++20 module partition implementation. ModulePartitionImplementation, /// This is the explicit Global Module Fragment of a modular TU. diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h index afdd0e8983c9e3a9bc8320cfc90c098c75cb443c..4456f4afd142df0c74023d74ff1640bb79fe1435 100644 --- a/clang/include/clang/Basic/OpenACCKinds.h +++ b/clang/include/clang/Basic/OpenACCKinds.h @@ -16,6 +16,7 @@ #include "clang/Basic/Diagnostic.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" namespace clang { // Represents the Construct/Directive kind of a pragma directive. Note the @@ -65,8 +66,9 @@ enum class OpenACCDirectiveKind { Invalid, }; -inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out, - OpenACCDirectiveKind K) { +template +inline StreamTy &PrintOpenACCDirectiveKind(StreamTy &Out, + OpenACCDirectiveKind K) { switch (K) { case OpenACCDirectiveKind::Parallel: return Out << "parallel"; @@ -134,6 +136,16 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out, llvm_unreachable("Uncovered directive kind"); } +inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out, + OpenACCDirectiveKind K) { + return PrintOpenACCDirectiveKind(Out, K); +} + +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out, + OpenACCDirectiveKind K) { + return PrintOpenACCDirectiveKind(Out, K); +} + enum class OpenACCAtomicKind { Read, Write, @@ -253,8 +265,8 @@ enum class OpenACCClauseKind { Invalid, }; -inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out, - OpenACCClauseKind K) { +template +inline StreamTy &PrintOpenACCClauseKind(StreamTy &Out, OpenACCClauseKind K) { switch (K) { case OpenACCClauseKind::Finalize: return Out << "finalize"; @@ -387,6 +399,17 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out, } llvm_unreachable("Uncovered clause kind"); } + +inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out, + OpenACCClauseKind K) { + return PrintOpenACCClauseKind(Out, K); +} + +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out, + OpenACCClauseKind K) { + return PrintOpenACCClauseKind(Out, K); +} + enum class OpenACCDefaultClauseKind { /// 'none' option. None, diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 9d03800840fcd0b5704a87fbaf85f4e65ffd7ed3..b4e3ae573b95e62af4fae5529bc8d1e52bbcf88c 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -296,3 +296,9 @@ def OMPTargetTeamsGenericLoopDirective : StmtNode; def OMPParallelGenericLoopDirective : StmtNode; def OMPTargetParallelGenericLoopDirective : StmtNode; def OMPErrorDirective : StmtNode; + +// OpenACC Constructs. +def OpenACCConstructStmt : StmtNode; +def OpenACCAssociatedStmtConstruct + : StmtNode; +def OpenACCComputeConstruct : StmtNode; diff --git a/clang/include/clang/Basic/TargetBuiltins.h b/clang/include/clang/Basic/TargetBuiltins.h index a4abaaef44c06c48d2dba01b28a5e6ff58435770..4333830bf34f24b8de7447a5632d469e97db8e99 100644 --- a/clang/include/clang/Basic/TargetBuiltins.h +++ b/clang/include/clang/Basic/TargetBuiltins.h @@ -159,7 +159,7 @@ namespace clang { FirstRVVBuiltin = clang::Builtin::FirstTSBuiltin, LastRVVBuiltin = RISCVVector::FirstTSBuiltin - 1, #define BUILTIN(ID, TYPE, ATTRS) BI##ID, -#include "clang/Basic/BuiltinsRISCV.def" +#include "clang/Basic/BuiltinsRISCV.inc" LastTSBuiltin }; } // namespace RISCV diff --git a/clang/include/clang/Basic/Visibility.h b/clang/include/clang/Basic/Visibility.h index 1e196300be421eb635b2bdc855dfc9dad444798b..b9693e613224c9ab210207afb62cdb17c855ac46 100644 --- a/clang/include/clang/Basic/Visibility.h +++ b/clang/include/clang/Basic/Visibility.h @@ -51,8 +51,11 @@ inline Visibility minVisibility(Visibility L, Visibility R) { } class LinkageInfo { + LLVM_PREFERRED_TYPE(Linkage) uint8_t linkage_ : 3; + LLVM_PREFERRED_TYPE(Visibility) uint8_t visibility_ : 2; + LLVM_PREFERRED_TYPE(bool) uint8_t explicit_ : 1; void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; } diff --git a/clang/include/clang/CodeGen/CGFunctionInfo.h b/clang/include/clang/CodeGen/CGFunctionInfo.h index e388901b8a504c5680f3ca88c017d65adde87527..811f33407368c6ce997a256f90261b4bae0b50e9 100644 --- a/clang/include/clang/CodeGen/CGFunctionInfo.h +++ b/clang/include/clang/CodeGen/CGFunctionInfo.h @@ -564,35 +564,45 @@ class CGFunctionInfo final unsigned EffectiveCallingConvention : 8; /// The clang::CallingConv that this was originally created with. + LLVM_PREFERRED_TYPE(CallingConv) unsigned ASTCallingConvention : 6; /// Whether this is an instance method. + LLVM_PREFERRED_TYPE(bool) unsigned InstanceMethod : 1; /// Whether this is a chain call. + LLVM_PREFERRED_TYPE(bool) unsigned ChainCall : 1; /// Whether this function is called by forwarding arguments. /// This doesn't support inalloca or varargs. + LLVM_PREFERRED_TYPE(bool) unsigned DelegateCall : 1; /// Whether this function is a CMSE nonsecure call + LLVM_PREFERRED_TYPE(bool) unsigned CmseNSCall : 1; /// Whether this function is noreturn. + LLVM_PREFERRED_TYPE(bool) unsigned NoReturn : 1; /// Whether this function is returns-retained. + LLVM_PREFERRED_TYPE(bool) unsigned ReturnsRetained : 1; /// Whether this function saved caller registers. + LLVM_PREFERRED_TYPE(bool) unsigned NoCallerSavedRegs : 1; /// How many arguments to pass inreg. + LLVM_PREFERRED_TYPE(bool) unsigned HasRegParm : 1; unsigned RegParm : 3; /// Whether this function has nocf_check attribute. + LLVM_PREFERRED_TYPE(bool) unsigned NoCfCheck : 1; /// Log 2 of the maximum vector width. @@ -604,6 +614,7 @@ class CGFunctionInfo final /// passing non-trivial types with inalloca. Not part of the profile. llvm::StructType *ArgStruct; unsigned ArgStructAlign : 31; + LLVM_PREFERRED_TYPE(bool) unsigned HasExtParameterInfos : 1; unsigned NumArgs; diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index 3ee1bcf2a69c9bd0a604bf7c36de864950767255..908bc87c14b1cac70f7b6f84315bc01705dcc7de 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -232,10 +232,12 @@ public: bool IsDXCMode() const { return Mode == DXCMode; } /// Only print tool bindings, don't build any jobs. + LLVM_PREFERRED_TYPE(bool) unsigned CCCPrintBindings : 1; /// Set CC_PRINT_OPTIONS mode, which is like -v but logs the commands to /// CCPrintOptionsFilename or to stderr. + LLVM_PREFERRED_TYPE(bool) unsigned CCPrintOptions : 1; /// The format of the header information that is emitted. If CC_PRINT_HEADERS @@ -252,17 +254,21 @@ public: /// Set CC_LOG_DIAGNOSTICS mode, which causes the frontend to log diagnostics /// to CCLogDiagnosticsFilename or to stderr, in a stable machine readable /// format. + LLVM_PREFERRED_TYPE(bool) unsigned CCLogDiagnostics : 1; /// Whether the driver is generating diagnostics for debugging purposes. + LLVM_PREFERRED_TYPE(bool) unsigned CCGenDiagnostics : 1; /// Set CC_PRINT_PROC_STAT mode, which causes the driver to dump /// performance report to CC_PRINT_PROC_STAT_FILE or to stdout. + LLVM_PREFERRED_TYPE(bool) unsigned CCPrintProcessStats : 1; /// Set CC_PRINT_INTERNAL_STAT mode, which causes the driver to dump internal /// performance report to CC_PRINT_INTERNAL_STAT_FILE or to stdout. + LLVM_PREFERRED_TYPE(bool) unsigned CCPrintInternalStats : 1; /// Pointer to the ExecuteCC1Tool function, if available. @@ -303,9 +309,11 @@ private: /// Whether to check that input files exist when constructing compilation /// jobs. + LLVM_PREFERRED_TYPE(bool) unsigned CheckInputsExist : 1; /// Whether to probe for PCH files on disk, in order to upgrade /// -include foo.h to -include-pch foo.h.pch. + LLVM_PREFERRED_TYPE(bool) unsigned ProbePrecompiled : 1; public: @@ -319,6 +327,7 @@ public: private: /// Certain options suppress the 'no input files' warning. + LLVM_PREFERRED_TYPE(bool) unsigned SuppressMissingInputWarning : 1; /// Cache of all the ToolChains in use by the driver. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 4b232b8aab722a1658ffbb65b5d388e8784a0a40..c625d0dd1c0c72f73089b5509c5b67f18cf9373e 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4414,7 +4414,7 @@ def mwatchsimulator_version_min_EQ : Joined<["-"], "mwatchsimulator-version-min= def march_EQ : Joined<["-"], "march=">, Group, Flags<[TargetSpecific]>, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, HelpText<"For a list of available architectures for the target use '-mcpu=help'">; -def masm_EQ : Joined<["-"], "masm=">, Group; +def masm_EQ : Joined<["-"], "masm=">, Group, Visibility<[ClangOption, FlangOption]>; def inline_asm_EQ : Joined<["-"], "inline-asm=">, Group, Visibility<[ClangOption, CC1Option]>, Values<"att,intel">, @@ -4614,6 +4614,10 @@ def msave_restore : Flag<["-"], "msave-restore">, Group, HelpText<"Enable using library calls for save and restore">; def mno_save_restore : Flag<["-"], "mno-save-restore">, Group, HelpText<"Disable using library calls for save and restore">; +def mforced_sw_shadow_stack : Flag<["-"], "mforced-sw-shadow-stack">, Group, + HelpText<"Force using software shadow stack when shadow-stack enabled">; +def mno_forced_sw_shadow_stack : Flag<["-"], "mno-forced-sw-shadow-stack">, Group, + HelpText<"Not force using software shadow stack when shadow-stack enabled">; } // let Flags = [TargetSpecific] let Flags = [TargetSpecific] in { def menable_experimental_extensions : Flag<["-"], "menable-experimental-extensions">, Group, @@ -5335,7 +5339,7 @@ def print_rocm_search_dirs : Flag<["-", "--"], "print-rocm-search-dirs">, HelpText<"Print the paths used for finding ROCm installation">, Visibility<[ClangOption, CLOption]>; def print_runtime_dir : Flag<["-", "--"], "print-runtime-dir">, - HelpText<"Print the directory pathname containing clangs runtime libraries">, + HelpText<"Print the directory pathname containing Clang's runtime libraries">, Visibility<[ClangOption, CLOption]>; def print_diagnostic_options : Flag<["-", "--"], "print-diagnostic-options">, HelpText<"Print all of Clang's warning options">, @@ -5392,11 +5396,13 @@ def regcall4 : Flag<["-"], "regcall4">, Group, MarshallingInfoFlag>; def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[NoXarchOption]>, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, - HelpText<"Save intermediate compilation results.">; + HelpText<"Save intermediate compilation results. can be set to 'cwd' for " + "current working directory, or 'obj' which will save temporary files in the " + "same directory as the final output file">; def save_temps : Flag<["-", "--"], "save-temps">, Flags<[NoXarchOption]>, Visibility<[ClangOption, FlangOption, FC1Option]>, Alias, AliasArgs<["cwd"]>, - HelpText<"Save intermediate compilation results">; + HelpText<"Alias for --save-temps=cwd">; def save_stats_EQ : Joined<["-", "--"], "save-stats=">, Flags<[NoXarchOption]>, HelpText<"Save llvm statistics.">; def save_stats : Flag<["-", "--"], "save-stats">, Flags<[NoXarchOption]>, @@ -5823,6 +5829,18 @@ def mvis3 : Flag<["-"], "mvis3">, Group; def mno_vis3 : Flag<["-"], "mno-vis3">, Group; def mhard_quad_float : Flag<["-"], "mhard-quad-float">, Group; def msoft_quad_float : Flag<["-"], "msoft-quad-float">, Group; +foreach i = 1 ... 7 in + def ffixed_g#i : Flag<["-"], "ffixed-g"#i>, Group, + HelpText<"Reserve the G"#i#" register (SPARC only)">; +foreach i = 0 ... 5 in + def ffixed_o#i : Flag<["-"], "ffixed-o"#i>, Group, + HelpText<"Reserve the O"#i#" register (SPARC only)">; +foreach i = 0 ... 7 in + def ffixed_l#i : Flag<["-"], "ffixed-l"#i>, Group, + HelpText<"Reserve the L"#i#" register (SPARC only)">; +foreach i = 0 ... 5 in + def ffixed_i#i : Flag<["-"], "ffixed-i"#i>, Group, + HelpText<"Reserve the I"#i#" register (SPARC only)">; } // let Flags = [TargetSpecific] // M68k features flags @@ -8448,8 +8466,8 @@ def _SLASH_ZW : CLJoined<"ZW">; // clang-dxc Options //===----------------------------------------------------------------------===// -def dxc_Group : OptionGroup<"">, Visibility<[DXCOption]>, - HelpText<"dxc compatibility options">; +def dxc_Group : OptionGroup<"clang-dxc options">, Visibility<[DXCOption]>, + HelpText<"dxc compatibility options.">; class DXCFlag : Option<["/", "-"], name, KIND_FLAG>, Group, Visibility<[DXCOption]>; class DXCJoinedOrSeparate : Option<["/", "-"], name, diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index cb14d98825400b392452d8b295ffdd5f3528a389..737cbfced9e9ceb789ce3153c55d1ba9fe91d01e 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -1010,8 +1010,9 @@ struct FormatStyle { /// \version 3.7 DefinitionReturnTypeBreakingStyle AlwaysBreakAfterDefinitionReturnType; - /// The function declaration return type breaking style to use. + /// This option is renamed to ``BreakAfterReturnType``. /// \version 3.8 + /// @deprecated ReturnTypeBreakingStyle AlwaysBreakAfterReturnType; /// If ``true``, always break before multiline string literals. @@ -1075,9 +1076,10 @@ struct FormatStyle { BTDS_Yes }; - /// The template declaration breaking style to use. + /// This option is renamed to ``BreakTemplateDeclarations``. /// \version 3.4 - BreakTemplateDeclarationsStyle AlwaysBreakTemplateDeclarations; + /// @deprecated + // BreakTemplateDeclarationsStyle AlwaysBreakTemplateDeclarations; /// A vector of strings that should be interpreted as attributes/qualifiers /// instead of identifiers. This can be useful for language extensions or @@ -1575,6 +1577,10 @@ struct FormatStyle { /// \version 16 AttributeBreakingStyle BreakAfterAttributes; + /// The function declaration return type breaking style to use. + /// \version 19 + // ReturnTypeBreakingStyle BreakAfterReturnType; + /// If ``true``, clang-format will always break after a Json array ``[`` /// otherwise it will scan until the closing ``]`` to determine if it should /// add newlines between elements (prettier compatible). @@ -2293,6 +2299,10 @@ struct FormatStyle { /// \version 7 BreakInheritanceListStyle BreakInheritanceList; + /// The template declaration breaking style to use. + /// \version 19 + BreakTemplateDeclarationsStyle BreakTemplateDeclarations; + /// If ``true``, consecutive namespace declarations will be on the same /// line. If ``false``, each namespace is declared on a new line. /// \code @@ -4817,8 +4827,6 @@ struct FormatStyle { AlwaysBreakAfterReturnType == R.AlwaysBreakAfterReturnType && AlwaysBreakBeforeMultilineStrings == R.AlwaysBreakBeforeMultilineStrings && - AlwaysBreakTemplateDeclarations == - R.AlwaysBreakTemplateDeclarations && AttributeMacros == R.AttributeMacros && BinPackArguments == R.BinPackArguments && BinPackParameters == R.BinPackParameters && @@ -4836,6 +4844,7 @@ struct FormatStyle { BreakConstructorInitializers == R.BreakConstructorInitializers && BreakInheritanceList == R.BreakInheritanceList && BreakStringLiterals == R.BreakStringLiterals && + BreakTemplateDeclarations == R.BreakTemplateDeclarations && ColumnLimit == R.ColumnLimit && CommentPragmas == R.CommentPragmas && CompactNamespaces == R.CompactNamespaces && ConstructorInitializerIndentWidth == diff --git a/clang/include/clang/Lex/PPCallbacks.h b/clang/include/clang/Lex/PPCallbacks.h index e3942af7be2803026c3243d1a6b5bd9e5721c90a..dfc74b52686f1e69c70d62bfa4632843c5457527 100644 --- a/clang/include/clang/Lex/PPCallbacks.h +++ b/clang/include/clang/Lex/PPCallbacks.h @@ -127,8 +127,10 @@ public: /// \param RelativePath The path relative to SearchPath, at which the include /// file was found. This is equal to FileName except for framework includes. /// - /// \param Imported The module, whenever an inclusion directive was - /// automatically turned into a module import or null otherwise. + /// \param SuggestedModule The module suggested for this header, if any. + /// + /// \param ModuleImported Whether this include was translated into import of + /// \p SuggestedModule. /// /// \param FileType The characteristic kind, indicates whether a file or /// directory holds normal user code, system code, or system code which is @@ -139,7 +141,8 @@ public: bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, StringRef RelativePath, - const Module *Imported, + const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) {} /// Callback invoked whenever a submodule was entered. @@ -473,14 +476,15 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override { First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, FilenameRange, File, SearchPath, RelativePath, - Imported, FileType); + SuggestedModule, ModuleImported, FileType); Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, FilenameRange, File, SearchPath, RelativePath, - Imported, FileType); + SuggestedModule, ModuleImported, FileType); } void EnteredSubmodule(Module *M, SourceLocation ImportLoc, diff --git a/clang/include/clang/Lex/PreprocessingRecord.h b/clang/include/clang/Lex/PreprocessingRecord.h index 5ddf024186f86553a73ba6c0ae21cab812ab65cd..437d8e4cc174ed56366127f31f16e85de6ffabc3 100644 --- a/clang/include/clang/Lex/PreprocessingRecord.h +++ b/clang/include/clang/Lex/PreprocessingRecord.h @@ -532,7 +532,8 @@ class Token; StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, + const Module *SuggestedModule, bool ModuleImported, SrcMgr::CharacteristicKind FileType) override; void Ifdef(SourceLocation Loc, const Token &MacroNameTok, const MacroDefinition &MD) override; diff --git a/clang/include/clang/Sema/AnalysisBasedWarnings.h b/clang/include/clang/Sema/AnalysisBasedWarnings.h index 020ddd36cf73eea0bcf5898ca6171a0073001536..aafe227b84084cd5069971c2afb0e2834e70ad84 100644 --- a/clang/include/clang/Sema/AnalysisBasedWarnings.h +++ b/clang/include/clang/Sema/AnalysisBasedWarnings.h @@ -34,9 +34,13 @@ public: class Policy { friend class AnalysisBasedWarnings; // The warnings to run. + LLVM_PREFERRED_TYPE(bool) unsigned enableCheckFallThrough : 1; + LLVM_PREFERRED_TYPE(bool) unsigned enableCheckUnreachable : 1; + LLVM_PREFERRED_TYPE(bool) unsigned enableThreadSafetyAnalysis : 1; + LLVM_PREFERRED_TYPE(bool) unsigned enableConsumedAnalysis : 1; public: Policy(); diff --git a/clang/include/clang/Sema/CodeCompleteConsumer.h b/clang/include/clang/Sema/CodeCompleteConsumer.h index 274eaac819af1bd65c97a311db4870bc0d4fb584..a2028e40f83d54c1008d78568ad67cfe47479449 100644 --- a/clang/include/clang/Sema/CodeCompleteConsumer.h +++ b/clang/include/clang/Sema/CodeCompleteConsumer.h @@ -581,6 +581,7 @@ private: unsigned Priority : 16; /// The availability of this code-completion result. + LLVM_PREFERRED_TYPE(CXAvailabilityKind) unsigned Availability : 2; /// The name of the parent context. diff --git a/clang/include/clang/Sema/CodeCompleteOptions.h b/clang/include/clang/Sema/CodeCompleteOptions.h index a3403b01dcde90394615736be006383c2fbf2287..d8dc386c4be412b606995eceb24ee37361ceb686 100644 --- a/clang/include/clang/Sema/CodeCompleteOptions.h +++ b/clang/include/clang/Sema/CodeCompleteOptions.h @@ -9,18 +9,23 @@ #ifndef LLVM_CLANG_SEMA_CODECOMPLETEOPTIONS_H #define LLVM_CLANG_SEMA_CODECOMPLETEOPTIONS_H +#include "llvm/Support/Compiler.h" + namespace clang { /// Options controlling the behavior of code completion. class CodeCompleteOptions { public: /// Show macros in code completion results. + LLVM_PREFERRED_TYPE(bool) unsigned IncludeMacros : 1; /// Show code patterns in code completion results. + LLVM_PREFERRED_TYPE(bool) unsigned IncludeCodePatterns : 1; /// Show top-level decls in code completion results. + LLVM_PREFERRED_TYPE(bool) unsigned IncludeGlobals : 1; /// Show decls in namespace (including the global namespace) in code @@ -29,18 +34,22 @@ public: /// Currently, this only works when completing qualified IDs (i.e. /// `Sema::CodeCompleteQualifiedId`). /// FIXME: consider supporting more completion cases with this option. + LLVM_PREFERRED_TYPE(bool) unsigned IncludeNamespaceLevelDecls : 1; /// Show brief documentation comments in code completion results. + LLVM_PREFERRED_TYPE(bool) unsigned IncludeBriefComments : 1; /// Hint whether to load data from the external AST to provide full results. /// If false, namespace-level declarations and macros from the preamble may be /// omitted. + LLVM_PREFERRED_TYPE(bool) unsigned LoadExternal : 1; /// Include results after corrections (small fix-its), e.g. change '.' to '->' /// on member access, etc. + LLVM_PREFERRED_TYPE(bool) unsigned IncludeFixIts : 1; CodeCompleteOptions() diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 77638def60063d9d9fa37510528f3f8691da0bce..d161147527dc349acbb7387b30bc5a1d068da9b5 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -353,36 +353,57 @@ public: private: // storage-class-specifier - /*SCS*/unsigned StorageClassSpec : 3; - /*TSCS*/unsigned ThreadStorageClassSpec : 2; + LLVM_PREFERRED_TYPE(SCS) + unsigned StorageClassSpec : 3; + LLVM_PREFERRED_TYPE(TSCS) + unsigned ThreadStorageClassSpec : 2; + LLVM_PREFERRED_TYPE(bool) unsigned SCS_extern_in_linkage_spec : 1; // type-specifier - /*TypeSpecifierWidth*/ unsigned TypeSpecWidth : 2; - /*TSC*/unsigned TypeSpecComplex : 2; - /*TSS*/unsigned TypeSpecSign : 2; - /*TST*/unsigned TypeSpecType : 7; + LLVM_PREFERRED_TYPE(TypeSpecifierWidth) + unsigned TypeSpecWidth : 2; + LLVM_PREFERRED_TYPE(TSC) + unsigned TypeSpecComplex : 2; + LLVM_PREFERRED_TYPE(TypeSpecifierSign) + unsigned TypeSpecSign : 2; + LLVM_PREFERRED_TYPE(TST) + unsigned TypeSpecType : 7; + LLVM_PREFERRED_TYPE(bool) unsigned TypeAltiVecVector : 1; + LLVM_PREFERRED_TYPE(bool) unsigned TypeAltiVecPixel : 1; + LLVM_PREFERRED_TYPE(bool) unsigned TypeAltiVecBool : 1; + LLVM_PREFERRED_TYPE(bool) unsigned TypeSpecOwned : 1; + LLVM_PREFERRED_TYPE(bool) unsigned TypeSpecPipe : 1; + LLVM_PREFERRED_TYPE(bool) unsigned TypeSpecSat : 1; + LLVM_PREFERRED_TYPE(bool) unsigned ConstrainedAuto : 1; // type-qualifiers + LLVM_PREFERRED_TYPE(TQ) unsigned TypeQualifiers : 5; // Bitwise OR of TQ. // function-specifier + LLVM_PREFERRED_TYPE(bool) unsigned FS_inline_specified : 1; + LLVM_PREFERRED_TYPE(bool) unsigned FS_forceinline_specified: 1; + LLVM_PREFERRED_TYPE(bool) unsigned FS_virtual_specified : 1; + LLVM_PREFERRED_TYPE(bool) unsigned FS_noreturn_specified : 1; // friend-specifier + LLVM_PREFERRED_TYPE(bool) unsigned Friend_specified : 1; // constexpr-specifier + LLVM_PREFERRED_TYPE(ConstexprSpecKind) unsigned ConstexprSpecifier : 2; union { @@ -1246,6 +1267,7 @@ struct DeclaratorChunk { struct PointerTypeInfo { /// The type qualifiers: const/volatile/restrict/unaligned/atomic. + LLVM_PREFERRED_TYPE(DeclSpec::TQ) unsigned TypeQuals : 5; /// The location of the const-qualifier, if any. @@ -1279,12 +1301,15 @@ struct DeclaratorChunk { struct ArrayTypeInfo { /// The type qualifiers for the array: /// const/volatile/restrict/__unaligned/_Atomic. + LLVM_PREFERRED_TYPE(DeclSpec::TQ) unsigned TypeQuals : 5; /// True if this dimension included the 'static' keyword. + LLVM_PREFERRED_TYPE(bool) unsigned hasStatic : 1; /// True if this dimension was [*]. In this case, NumElts is null. + LLVM_PREFERRED_TYPE(bool) unsigned isStar : 1; /// This is the size of the array, or null if [] or [*] was specified. @@ -1331,28 +1356,35 @@ struct DeclaratorChunk { /// hasPrototype - This is true if the function had at least one typed /// parameter. If the function is () or (a,b,c), then it has no prototype, /// and is treated as a K&R-style function. + LLVM_PREFERRED_TYPE(bool) unsigned hasPrototype : 1; /// isVariadic - If this function has a prototype, and if that /// proto ends with ',...)', this is true. When true, EllipsisLoc /// contains the location of the ellipsis. + LLVM_PREFERRED_TYPE(bool) unsigned isVariadic : 1; /// Can this declaration be a constructor-style initializer? + LLVM_PREFERRED_TYPE(bool) unsigned isAmbiguous : 1; /// Whether the ref-qualifier (if any) is an lvalue reference. /// Otherwise, it's an rvalue reference. + LLVM_PREFERRED_TYPE(bool) unsigned RefQualifierIsLValueRef : 1; /// ExceptionSpecType - An ExceptionSpecificationType value. + LLVM_PREFERRED_TYPE(ExceptionSpecificationType) unsigned ExceptionSpecType : 4; /// DeleteParams - If this is true, we need to delete[] Params. + LLVM_PREFERRED_TYPE(bool) unsigned DeleteParams : 1; /// HasTrailingReturnType - If this is true, a trailing return type was /// specified. + LLVM_PREFERRED_TYPE(bool) unsigned HasTrailingReturnType : 1; /// The location of the left parenthesis in the source. @@ -1567,6 +1599,7 @@ struct DeclaratorChunk { struct BlockPointerTypeInfo { /// For now, sema will catch these as invalid. /// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic. + LLVM_PREFERRED_TYPE(DeclSpec::TQ) unsigned TypeQuals : 5; void destroy() { @@ -1575,6 +1608,7 @@ struct DeclaratorChunk { struct MemberPointerTypeInfo { /// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic. + LLVM_PREFERRED_TYPE(DeclSpec::TQ) unsigned TypeQuals : 5; /// Location of the '*' token. SourceLocation StarLoc; @@ -1767,6 +1801,7 @@ private: /// The bindings. Binding *Bindings; unsigned NumBindings : 31; + LLVM_PREFERRED_TYPE(bool) unsigned DeleteBindings : 1; friend class Declarator; @@ -1883,33 +1918,42 @@ private: SmallVector DeclTypeInfo; /// InvalidType - Set by Sema::GetTypeForDeclarator(). + LLVM_PREFERRED_TYPE(bool) unsigned InvalidType : 1; /// GroupingParens - Set by Parser::ParseParenDeclarator(). + LLVM_PREFERRED_TYPE(bool) unsigned GroupingParens : 1; /// FunctionDefinition - Is this Declarator for a function or member /// definition and, if so, what kind? /// /// Actually a FunctionDefinitionKind. + LLVM_PREFERRED_TYPE(FunctionDefinitionKind) unsigned FunctionDefinition : 2; /// Is this Declarator a redeclaration? + LLVM_PREFERRED_TYPE(bool) unsigned Redeclaration : 1; /// true if the declaration is preceded by \c __extension__. + LLVM_PREFERRED_TYPE(bool) unsigned Extension : 1; /// Indicates whether this is an Objective-C instance variable. + LLVM_PREFERRED_TYPE(bool) unsigned ObjCIvar : 1; /// Indicates whether this is an Objective-C 'weak' property. + LLVM_PREFERRED_TYPE(bool) unsigned ObjCWeakProperty : 1; /// Indicates whether the InlineParams / InlineBindings storage has been used. + LLVM_PREFERRED_TYPE(bool) unsigned InlineStorageUsed : 1; /// Indicates whether this declarator has an initializer. + LLVM_PREFERRED_TYPE(bool) unsigned HasInitializer : 1; /// Attributes attached to the declarator. diff --git a/clang/include/clang/Sema/DelayedDiagnostic.h b/clang/include/clang/Sema/DelayedDiagnostic.h index 9de7131f74c70ec2a8cc106ee94c40c271f6e4ee..0105089a393f175ed178e990faa2aec34127c6a4 100644 --- a/clang/include/clang/Sema/DelayedDiagnostic.h +++ b/clang/include/clang/Sema/DelayedDiagnostic.h @@ -111,7 +111,9 @@ public: } private: + LLVM_PREFERRED_TYPE(AccessSpecifier) unsigned Access : 2; + LLVM_PREFERRED_TYPE(bool) unsigned IsMember : 1; NamedDecl *Target; CXXRecordDecl *NamingClass; diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 6ccabad3af54468a73388183cc281403df491027..9b342c09168444ecf798a257b1664b8e50d32f93 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -278,40 +278,50 @@ class Sema; /// Whether this is the deprecated conversion of a /// string literal to a pointer to non-const character data /// (C++ 4.2p2). + LLVM_PREFERRED_TYPE(bool) unsigned DeprecatedStringLiteralToCharPtr : 1; /// Whether the qualification conversion involves a change in the /// Objective-C lifetime (for automatic reference counting). + LLVM_PREFERRED_TYPE(bool) unsigned QualificationIncludesObjCLifetime : 1; /// IncompatibleObjC - Whether this is an Objective-C conversion /// that we should warn about (if we actually use it). + LLVM_PREFERRED_TYPE(bool) unsigned IncompatibleObjC : 1; /// ReferenceBinding - True when this is a reference binding /// (C++ [over.ics.ref]). + LLVM_PREFERRED_TYPE(bool) unsigned ReferenceBinding : 1; /// DirectBinding - True when this is a reference binding that is a /// direct binding (C++ [dcl.init.ref]). + LLVM_PREFERRED_TYPE(bool) unsigned DirectBinding : 1; /// Whether this is an lvalue reference binding (otherwise, it's /// an rvalue reference binding). + LLVM_PREFERRED_TYPE(bool) unsigned IsLvalueReference : 1; /// Whether we're binding to a function lvalue. + LLVM_PREFERRED_TYPE(bool) unsigned BindsToFunctionLvalue : 1; /// Whether we're binding to an rvalue. + LLVM_PREFERRED_TYPE(bool) unsigned BindsToRvalue : 1; /// Whether this binds an implicit object argument to a /// non-static member function without a ref-qualifier. + LLVM_PREFERRED_TYPE(bool) unsigned BindsImplicitObjectArgumentWithoutRefQualifier : 1; /// Whether this binds a reference to an object with a different /// Objective-C lifetime qualifier. + LLVM_PREFERRED_TYPE(bool) unsigned ObjCLifetimeConversionBinding : 1; /// FromType - The type that this conversion is converting @@ -541,9 +551,11 @@ class Sema; }; /// ConversionKind - The kind of implicit conversion sequence. + LLVM_PREFERRED_TYPE(Kind) unsigned ConversionKind : 31; // Whether the initializer list was of an incomplete array. + LLVM_PREFERRED_TYPE(bool) unsigned InitializerListOfIncompleteArray : 1; /// When initializing an array or std::initializer_list from an @@ -878,6 +890,7 @@ class Sema; CallExpr::ADLCallKind IsADLCandidate : 1; /// Whether this is a rewritten candidate, and if so, of what kind? + LLVM_PREFERRED_TYPE(OverloadCandidateRewriteKind) unsigned RewriteKind : 2; /// FailureKind - The reason why this candidate is not viable. diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h index 8c0edca1ebc5eeee613cbfb5e960d4f0e47d3ea2..8c3ba39031aad868c5986a01cf6ced0e7f3eb880 100644 --- a/clang/include/clang/Sema/ParsedAttr.h +++ b/clang/include/clang/Sema/ParsedAttr.h @@ -82,7 +82,9 @@ struct AvailabilityData { struct TypeTagForDatatypeData { ParsedType MatchingCType; + LLVM_PREFERRED_TYPE(bool) unsigned LayoutCompatible : 1; + LLVM_PREFERRED_TYPE(bool) unsigned MustBeNull : 1; }; struct PropertyData { @@ -149,33 +151,41 @@ private: unsigned NumArgs : 16; /// True if already diagnosed as invalid. + LLVM_PREFERRED_TYPE(bool) mutable unsigned Invalid : 1; /// True if this attribute was used as a type attribute. + LLVM_PREFERRED_TYPE(bool) mutable unsigned UsedAsTypeAttr : 1; /// True if this has the extra information associated with an /// availability attribute. + LLVM_PREFERRED_TYPE(bool) unsigned IsAvailability : 1; /// True if this has extra information associated with a /// type_tag_for_datatype attribute. + LLVM_PREFERRED_TYPE(bool) unsigned IsTypeTagForDatatype : 1; /// True if this has extra information associated with a /// Microsoft __delcspec(property) attribute. + LLVM_PREFERRED_TYPE(bool) unsigned IsProperty : 1; /// True if this has a ParsedType + LLVM_PREFERRED_TYPE(bool) unsigned HasParsedType : 1; /// True if the processing cache is valid. + LLVM_PREFERRED_TYPE(bool) mutable unsigned HasProcessingCache : 1; /// A cached value. mutable unsigned ProcessingCache : 8; /// True if the attribute is specified using '#pragma clang attribute'. + LLVM_PREFERRED_TYPE(bool) mutable unsigned IsPragmaClangAttribute : 1; /// The location of the 'unavailable' keyword in an diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h index 6eaa74382685baca951e1eb9ca10f7f76bfc00af..700e361ef83f13c0265ab54c0a1e2161fdb425eb 100644 --- a/clang/include/clang/Sema/ScopeInfo.h +++ b/clang/include/clang/Sema/ScopeInfo.h @@ -97,6 +97,8 @@ public: : PD(PD), Loc(Loc), Stmts(Stmts) {} }; +enum class FirstCoroutineStmtKind { CoReturn, CoAwait, CoYield }; + /// Retains information about a function, method, or block that is /// currently being parsed. class FunctionScopeInfo { @@ -170,6 +172,7 @@ public: /// An enumeration representing the kind of the first coroutine statement /// in the function. One of co_return, co_await, or co_yield. + LLVM_PREFERRED_TYPE(FirstCoroutineStmtKind) unsigned char FirstCoroutineStmtKind : 2; /// Whether we found an immediate-escalating expression. @@ -502,22 +505,30 @@ public: assert(FirstCoroutineStmtLoc.isInvalid() && "first coroutine statement location already set"); FirstCoroutineStmtLoc = Loc; - FirstCoroutineStmtKind = llvm::StringSwitch(Keyword) - .Case("co_return", 0) - .Case("co_await", 1) - .Case("co_yield", 2); + FirstCoroutineStmtKind = + llvm::StringSwitch(Keyword) + .Case("co_return", + llvm::to_underlying(FirstCoroutineStmtKind::CoReturn)) + .Case("co_await", + llvm::to_underlying(FirstCoroutineStmtKind::CoAwait)) + .Case("co_yield", + llvm::to_underlying(FirstCoroutineStmtKind::CoYield)); } StringRef getFirstCoroutineStmtKeyword() const { assert(FirstCoroutineStmtLoc.isValid() && "no coroutine statement available"); - switch (FirstCoroutineStmtKind) { - case 0: return "co_return"; - case 1: return "co_await"; - case 2: return "co_yield"; - default: - llvm_unreachable("FirstCoroutineStmtKind has an invalid value"); + auto Value = + static_cast(FirstCoroutineStmtKind); + switch (Value) { + case FirstCoroutineStmtKind::CoReturn: + return "co_return"; + case FirstCoroutineStmtKind::CoAwait: + return "co_await"; + case FirstCoroutineStmtKind::CoYield: + return "co_yield"; }; + llvm_unreachable("FirstCoroutineStmtKind has an invalid value"); } void setNeedsCoroutineSuspends(bool value = true) { @@ -582,25 +593,31 @@ class Capture { QualType CaptureType; /// The CaptureKind of this capture. + LLVM_PREFERRED_TYPE(CaptureKind) unsigned Kind : 2; /// Whether this is a nested capture (a capture of an enclosing capturing /// scope's capture). + LLVM_PREFERRED_TYPE(bool) unsigned Nested : 1; /// Whether this is a capture of '*this'. + LLVM_PREFERRED_TYPE(bool) unsigned CapturesThis : 1; /// Whether an explicit capture has been odr-used in the body of the /// lambda. + LLVM_PREFERRED_TYPE(bool) unsigned ODRUsed : 1; /// Whether an explicit capture has been non-odr-used in the body of /// the lambda. + LLVM_PREFERRED_TYPE(bool) unsigned NonODRUsed : 1; /// Whether the capture is invalid (a capture was required but the entity is /// non-capturable). + LLVM_PREFERRED_TYPE(bool) unsigned Invalid : 1; public: @@ -925,8 +942,8 @@ public: /// that were defined in parent contexts. Used to avoid warnings when the /// shadowed variables are uncaptured by this lambda. struct ShadowedOuterDecl { - const VarDecl *VD; - const VarDecl *ShadowedDecl; + const NamedDecl *VD; + const NamedDecl *ShadowedDecl; }; llvm::SmallVector ShadowingDecls; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 3c26003b5bda7f5455ec5896976a566cb3471cea..ed933f27f8df6bd3b144943fb005e88ffc7ea9e4 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -353,6 +353,72 @@ private: llvm::function_ref ComputeType; }; +/// Describes the result of template argument deduction. +/// +/// The TemplateDeductionResult enumeration describes the result of +/// template argument deduction, as returned from +/// DeduceTemplateArguments(). The separate TemplateDeductionInfo +/// structure provides additional information about the results of +/// template argument deduction, e.g., the deduced template argument +/// list (if successful) or the specific template parameters or +/// deduced arguments that were involved in the failure. +enum class TemplateDeductionResult { + /// Template argument deduction was successful. + Success = 0, + /// The declaration was invalid; do nothing. + Invalid, + /// Template argument deduction exceeded the maximum template + /// instantiation depth (which has already been diagnosed). + InstantiationDepth, + /// Template argument deduction did not deduce a value + /// for every template parameter. + Incomplete, + /// Template argument deduction did not deduce a value for every + /// expansion of an expanded template parameter pack. + IncompletePack, + /// Template argument deduction produced inconsistent + /// deduced values for the given template parameter. + Inconsistent, + /// Template argument deduction failed due to inconsistent + /// cv-qualifiers on a template parameter type that would + /// otherwise be deduced, e.g., we tried to deduce T in "const T" + /// but were given a non-const "X". + Underqualified, + /// Substitution of the deduced template argument values + /// resulted in an error. + SubstitutionFailure, + /// After substituting deduced template arguments, a dependent + /// parameter type did not match the corresponding argument. + DeducedMismatch, + /// After substituting deduced template arguments, an element of + /// a dependent parameter type did not match the corresponding element + /// of the corresponding argument (when deducing from an initializer list). + DeducedMismatchNested, + /// A non-depnedent component of the parameter did not match the + /// corresponding component of the argument. + NonDeducedMismatch, + /// When performing template argument deduction for a function + /// template, there were too many call arguments. + TooManyArguments, + /// When performing template argument deduction for a function + /// template, there were too few call arguments. + TooFewArguments, + /// The explicitly-specified template arguments were not valid + /// template arguments for the given template. + InvalidExplicitArguments, + /// Checking non-dependent argument conversions failed. + NonDependentConversionFailure, + /// The deduced arguments did not satisfy the constraints associated + /// with the template. + ConstraintsNotSatisfied, + /// Deduction failed; that's all we know. + MiscellaneousDeductionFailure, + /// CUDA Target attributes do not match. + CUDATargetMismatch, + /// Some error which was already diagnosed. + AlreadyDiagnosed +}; + /// Sema - This implements semantic analysis and AST building for C. class Sema final { Sema(const Sema &) = delete; @@ -3501,29 +3567,29 @@ public: /// For a defaulted function, the kind of defaulted function that it is. class DefaultedFunctionKind { - CXXSpecialMember SpecialMember : 8; - DefaultedComparisonKind Comparison : 8; + unsigned SpecialMember : 8; + unsigned Comparison : 8; public: DefaultedFunctionKind() - : SpecialMember(CXXInvalid), Comparison(DefaultedComparisonKind::None) { + : SpecialMember(CXXInvalid), Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) { } DefaultedFunctionKind(CXXSpecialMember CSM) - : SpecialMember(CSM), Comparison(DefaultedComparisonKind::None) {} + : SpecialMember(CSM), Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) {} DefaultedFunctionKind(DefaultedComparisonKind Comp) - : SpecialMember(CXXInvalid), Comparison(Comp) {} + : SpecialMember(CXXInvalid), Comparison(llvm::to_underlying(Comp)) {} bool isSpecialMember() const { return SpecialMember != CXXInvalid; } bool isComparison() const { - return Comparison != DefaultedComparisonKind::None; + return static_cast(Comparison) != DefaultedComparisonKind::None; } explicit operator bool() const { return isSpecialMember() || isComparison(); } - CXXSpecialMember asSpecialMember() const { return SpecialMember; } - DefaultedComparisonKind asComparison() const { return Comparison; } + CXXSpecialMember asSpecialMember() const { return static_cast(SpecialMember); } + DefaultedComparisonKind asComparison() const { return static_cast(Comparison); } /// Get the index of this function kind for use in diagnostics. unsigned getDiagnosticIndex() const { @@ -3531,7 +3597,7 @@ public: "invalid should have highest index"); static_assert((unsigned)DefaultedComparisonKind::None == 0, "none should be equal to zero"); - return SpecialMember + (unsigned)Comparison; + return SpecialMember + Comparison; } }; @@ -4838,13 +4904,12 @@ public: llvm::Error isValidSectionSpecifier(StringRef Str); bool checkSectionName(SourceLocation LiteralLoc, StringRef Str); bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str); - bool checkTargetVersionAttr(SourceLocation LiteralLoc, StringRef &Str, - bool &isDefault); - bool - checkTargetClonesAttrString(SourceLocation LiteralLoc, StringRef Str, - const StringLiteral *Literal, bool &HasDefault, - bool &HasCommas, bool &HasNotDefault, - SmallVectorImpl> &StringsBuffer); + bool checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D, + StringRef &Str, bool &isDefault); + bool checkTargetClonesAttrString( + SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal, + Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault, + SmallVectorImpl> &StringsBuffer); bool checkMSInheritanceAttrOnDefinition( CXXRecordDecl *RD, SourceRange Range, bool BestCase, MSInheritanceModel SemanticSpelling); @@ -9262,72 +9327,6 @@ public: QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType, bool AdjustExceptionSpec = false); - /// Describes the result of template argument deduction. - /// - /// The TemplateDeductionResult enumeration describes the result of - /// template argument deduction, as returned from - /// DeduceTemplateArguments(). The separate TemplateDeductionInfo - /// structure provides additional information about the results of - /// template argument deduction, e.g., the deduced template argument - /// list (if successful) or the specific template parameters or - /// deduced arguments that were involved in the failure. - enum TemplateDeductionResult { - /// Template argument deduction was successful. - TDK_Success = 0, - /// The declaration was invalid; do nothing. - TDK_Invalid, - /// Template argument deduction exceeded the maximum template - /// instantiation depth (which has already been diagnosed). - TDK_InstantiationDepth, - /// Template argument deduction did not deduce a value - /// for every template parameter. - TDK_Incomplete, - /// Template argument deduction did not deduce a value for every - /// expansion of an expanded template parameter pack. - TDK_IncompletePack, - /// Template argument deduction produced inconsistent - /// deduced values for the given template parameter. - TDK_Inconsistent, - /// Template argument deduction failed due to inconsistent - /// cv-qualifiers on a template parameter type that would - /// otherwise be deduced, e.g., we tried to deduce T in "const T" - /// but were given a non-const "X". - TDK_Underqualified, - /// Substitution of the deduced template argument values - /// resulted in an error. - TDK_SubstitutionFailure, - /// After substituting deduced template arguments, a dependent - /// parameter type did not match the corresponding argument. - TDK_DeducedMismatch, - /// After substituting deduced template arguments, an element of - /// a dependent parameter type did not match the corresponding element - /// of the corresponding argument (when deducing from an initializer list). - TDK_DeducedMismatchNested, - /// A non-depnedent component of the parameter did not match the - /// corresponding component of the argument. - TDK_NonDeducedMismatch, - /// When performing template argument deduction for a function - /// template, there were too many call arguments. - TDK_TooManyArguments, - /// When performing template argument deduction for a function - /// template, there were too few call arguments. - TDK_TooFewArguments, - /// The explicitly-specified template arguments were not valid - /// template arguments for the given template. - TDK_InvalidExplicitArguments, - /// Checking non-dependent argument conversions failed. - TDK_NonDependentConversionFailure, - /// The deduced arguments did not satisfy the constraints associated - /// with the template. - TDK_ConstraintsNotSatisfied, - /// Deduction failed; that's all we know. - TDK_MiscellaneousDeductionFailure, - /// CUDA Target attributes do not match. - TDK_CUDATargetMismatch, - /// Some error which was already diagnosed. - TDK_AlreadyDiagnosed - }; - TemplateDeductionResult DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, ArrayRef TemplateArgs, @@ -14445,7 +14444,7 @@ public: }; DeductionFailureInfo -MakeDeductionFailureInfo(ASTContext &Context, Sema::TemplateDeductionResult TDK, +MakeDeductionFailureInfo(ASTContext &Context, TemplateDeductionResult TDK, sema::TemplateDeductionInfo &Info); /// Contains a late templated function. diff --git a/clang/include/clang/Sema/TemplateDeduction.h b/clang/include/clang/Sema/TemplateDeduction.h index 85691c66a04433d9e627289d52d2f056725286ed..28b014fd84e4b35a641f925080cf4551208e9870 100644 --- a/clang/include/clang/Sema/TemplateDeduction.h +++ b/clang/include/clang/Sema/TemplateDeduction.h @@ -33,6 +33,7 @@ namespace clang { class Decl; struct DeducedPack; class Sema; +enum class TemplateDeductionResult; namespace sema { @@ -295,6 +296,10 @@ struct DeductionFailureInfo { /// Free any memory associated with this deduction failure. void Destroy(); + + TemplateDeductionResult getResult() const { + return static_cast(Result); + } }; /// TemplateSpecCandidate - This is a generalization of OverloadCandidate diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 9de925163599d4db22a0f6300780759e351ddd7f..f31efa5117f0d1e7d414fb23ec24bf3c98739b6e 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -2018,6 +2018,9 @@ enum StmtCode { // SYCLUniqueStableNameExpr EXPR_SYCL_UNIQUE_STABLE_NAME, + + // OpenACC Constructs + STMT_OPENACC_COMPUTE_CONSTRUCT, }; /// The kinds of designators that can occur in a diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index a4c7f54ab9e8b5551e84adeeb9b104e902320382..2002bf23c9595f7f21598db723f2e20506482258 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -721,6 +721,7 @@ private: unsigned ID; /// Whether this is a wildcard export. + LLVM_PREFERRED_TYPE(bool) unsigned IsWildcard : 1; /// String data. diff --git a/clang/include/clang/Support/RISCVVIntrinsicUtils.h b/clang/include/clang/Support/RISCVVIntrinsicUtils.h index 30bf36edb7bfc94b78c288e6d5b6939f54b8b3ec..ef9d6c15724b68856f8ed99e7be0e4af4338da43 100644 --- a/clang/include/clang/Support/RISCVVIntrinsicUtils.h +++ b/clang/include/clang/Support/RISCVVIntrinsicUtils.h @@ -554,7 +554,9 @@ struct RVVIntrinsicRecord { bool HasMaskPolicy : 1; bool HasFRMRoundModeOp : 1; bool IsTuple : 1; + LLVM_PREFERRED_TYPE(PolicyScheme) uint8_t UnMaskedPolicyScheme : 2; + LLVM_PREFERRED_TYPE(PolicyScheme) uint8_t MaskedPolicyScheme : 2; }; diff --git a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h index 051363b075de9972b2101fb42279aff39044d4d5..13ad2530864927c52fb48595bfe416b7c2c2f77c 100644 --- a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h +++ b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h @@ -166,7 +166,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override; void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path, const Module *Imported) override; diff --git a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h index c91e4a6b0ac54ac6ef003e1b5530383761237ad8..d167b7e45467fea5fd708b120a2e5feecdbeb5c4 100644 --- a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h +++ b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h @@ -164,7 +164,7 @@ struct IncludeStyle { /// When guessing whether a #include is the "main" include, only the include /// directives that use the specified character are considered. - /// \version 18 + /// \version 19 MainIncludeCharDiscriminator MainIncludeChar; }; diff --git a/clang/include/module.modulemap b/clang/include/module.modulemap index 794526bc289c0b6d82450d1c15b8ae72e802fa08..acd960c9c932ac0058b4e0f1521885ec9f8695ec 100644 --- a/clang/include/module.modulemap +++ b/clang/include/module.modulemap @@ -54,7 +54,6 @@ module Clang_Basic { textual header "clang/Basic/BuiltinsNEON.def" textual header "clang/Basic/BuiltinsNVPTX.def" textual header "clang/Basic/BuiltinsPPC.def" - textual header "clang/Basic/BuiltinsRISCV.def" textual header "clang/Basic/BuiltinsRISCVVector.def" textual header "clang/Basic/BuiltinsSME.def" textual header "clang/Basic/BuiltinsSVE.def" @@ -81,6 +80,7 @@ module Clang_Basic { textual header "clang/Basic/RISCVVTypes.def" textual header "clang/Basic/Sanitizers.def" textual header "clang/Basic/TargetCXXABI.def" + textual header "clang/Basic/TargetOSMacros.def" textual header "clang/Basic/TransformTypeTraits.def" textual header "clang/Basic/TokenKinds.def" textual header "clang/Basic/WebAssemblyReferenceTypes.def" diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 3b7ebbbd89ea219eeb3562c3899ffb40c7cd5b9a..fe6e03ce174e591b06f4a77437621f72a9593ed2 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -74,6 +74,7 @@ #include "clang/AST/ExprOpenMP.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index ebcb3952198a5b57375887b4930da5e8e1ea1167..49dcf2e4da3e77429c581db4105b3bcc056f9b78 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -112,6 +112,7 @@ add_clang_library(clangAST StmtCXX.cpp StmtIterator.cpp StmtObjC.cpp + StmtOpenACC.cpp StmtOpenMP.cpp StmtPrinter.cpp StmtProfile.cpp diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 26fdfa040796ed4eea201b01c75ba1b842e1c156..5d6bb72a208a1a7f5fdc45710a9391a494f8b3f5 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3537,10 +3537,23 @@ bool FunctionDecl::isTargetMultiVersion() const { (hasAttr() || hasAttr()); } +bool FunctionDecl::isTargetMultiVersionDefault() const { + if (!isMultiVersion()) + return false; + if (hasAttr()) + return getAttr()->isDefaultVersion(); + return hasAttr() && + getAttr()->isDefaultVersion(); +} + bool FunctionDecl::isTargetClonesMultiVersion() const { return isMultiVersion() && hasAttr(); } +bool FunctionDecl::isTargetVersionMultiVersion() const { + return isMultiVersion() && hasAttr(); +} + void FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { redeclarable_base::setPreviousDecl(PrevDecl); diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 822ac12c4c7dd4a3d3d7f11245385c1d37527d3f..43d221968ea3fba214a753266cf05426db1217ed 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -1215,6 +1215,10 @@ void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params, bool OmitTemplateKW) { assert(Params); + // Don't print invented template parameter lists. + if (!Params->empty() && Params->getParam(0)->isImplicit()) + return; + if (!OmitTemplateKW) Out << "template "; Out << '<'; diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index d665a08deb47e68f9b01217361ad79a27562d335..8b10e289583260f0bd6282621907ff0c45fe9f6c 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -3328,6 +3328,12 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, DIUE->getUpdater()->isConstantInitializer(Ctx, false, Culprit); } case InitListExprClass: { + // C++ [dcl.init.aggr]p2: + // The elements of an aggregate are: + // - for an array, the array elements in increasing subscript order, or + // - for a class, the direct base classes in declaration order, followed + // by the direct non-static data members (11.4) that are not members of + // an anonymous union, in declaration order. const InitListExpr *ILE = cast(this); assert(ILE->isSemanticForm() && "InitListExpr must be in semantic form"); if (ILE->getType()->isArrayType()) { @@ -3342,6 +3348,19 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, if (ILE->getType()->isRecordType()) { unsigned ElementNo = 0; RecordDecl *RD = ILE->getType()->castAs()->getDecl(); + + // In C++17, bases were added to the list of members used by aggregate + // initialization. + if (const auto *CXXRD = dyn_cast(RD)) { + for (unsigned i = 0, e = CXXRD->getNumBases(); i < e; i++) { + if (ElementNo < ILE->getNumInits()) { + const Expr *Elt = ILE->getInit(ElementNo++); + if (!Elt->isConstantInitializer(Ctx, false, Culprit)) + return false; + } + } + } + for (const auto *Field : RD->fields()) { // If this is a union, skip all the fields that aren't being initialized. if (RD->isUnion() && ILE->getInitializedFieldInUnion() != Field) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 089bc2094567f74252a81a1c571368458e9eb8d3..33ad94e6795c834f477c07c8b72e30f2841b3770 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -240,15 +240,19 @@ namespace { /// True if the subobject was named in a manner not supported by C++11. Such /// lvalues can still be folded, but they are not core constant expressions /// and we cannot perform lvalue-to-rvalue conversions on them. + LLVM_PREFERRED_TYPE(bool) unsigned Invalid : 1; /// Is this a pointer one past the end of an object? + LLVM_PREFERRED_TYPE(bool) unsigned IsOnePastTheEnd : 1; /// Indicator of whether the first entry is an unsized array. + LLVM_PREFERRED_TYPE(bool) unsigned FirstEntryIsAnUnsizedArray : 1; /// Indicator of whether the most-derived object is an array element. + LLVM_PREFERRED_TYPE(bool) unsigned MostDerivedIsArrayElement : 1; /// The length of the path to the most-derived object of which this is a @@ -8006,7 +8010,8 @@ public: assert(CorrespondingCallOpSpecialization && "We must always have a function call operator specialization " "that corresponds to our static invoker specialization"); - FD = cast(CorrespondingCallOpSpecialization); + assert(isa(CorrespondingCallOpSpecialization)); + FD = CorrespondingCallOpSpecialization; } else FD = LambdaCallOp; } else if (FD->isReplaceableGlobalAllocationFunction()) { diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/clang/lib/AST/Interp/ByteCodeEmitter.cpp index 8bbfa928bd64573fc78c49baae47b7bfd40d2879..e697e24fb341d275a38759d9ff1a36e28e4a9db9 100644 --- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp +++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp @@ -23,6 +23,34 @@ using namespace clang; using namespace clang::interp; Function *ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) { + bool IsLambdaStaticInvoker = false; + if (const auto *MD = dyn_cast(FuncDecl); + MD && MD->isLambdaStaticInvoker()) { + // For a lambda static invoker, we might have to pick a specialized + // version if the lambda is generic. In that case, the picked function + // will *NOT* be a static invoker anymore. However, it will still + // be a non-static member function, this (usually) requiring an + // instance pointer. We suppress that later in this function. + IsLambdaStaticInvoker = true; + + const CXXRecordDecl *ClosureClass = MD->getParent(); + assert(ClosureClass->captures_begin() == ClosureClass->captures_end()); + if (ClosureClass->isGenericLambda()) { + const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator(); + assert(MD->isFunctionTemplateSpecialization() && + "A generic lambda's static-invoker function must be a " + "template specialization"); + const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs(); + FunctionTemplateDecl *CallOpTemplate = + LambdaCallOp->getDescribedFunctionTemplate(); + void *InsertPos = nullptr; + const FunctionDecl *CorrespondingCallOpSpecialization = + CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos); + assert(CorrespondingCallOpSpecialization); + FuncDecl = cast(CorrespondingCallOpSpecialization); + } + } + // Set up argument indices. unsigned ParamOffset = 0; SmallVector ParamTypes; @@ -46,7 +74,7 @@ Function *ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) { // InterpStack when calling the function. bool HasThisPointer = false; if (const auto *MD = dyn_cast(FuncDecl)) { - if (MD->isImplicitObjectMemberFunction()) { + if (MD->isImplicitObjectMemberFunction() && !IsLambdaStaticInvoker) { HasThisPointer = true; ParamTypes.push_back(PT_Ptr); ParamOffsets.push_back(ParamOffset); diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 59fddfc2da19577b99d2dd2dbae4d06c93f93a65..91b9985eefbd30c55f209091be1e907e96d80ed2 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -167,7 +167,9 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitNull(classifyPrim(CE->getType()), CE); case CK_PointerToIntegral: { - // TODO: Discard handling. + if (DiscardResult) + return this->discard(SubExpr); + if (!this->visit(SubExpr)) return false; @@ -464,7 +466,7 @@ bool ByteCodeExprGen::VisitBinaryOperator(const BinaryOperator *BO) { // Special case for C++'s three-way/spaceship operator <=>, which // returns a std::{strong,weak,partial}_ordering (which is a class, so doesn't // have a PrimType). - if (!T && Ctx.getLangOpts().CPlusPlus) { + if (!T && BO->getOpcode() == BO_Cmp) { if (DiscardResult) return true; const ComparisonCategoryInfo *CmpInfo = @@ -1750,8 +1752,7 @@ bool ByteCodeExprGen::VisitPredefinedExpr(const PredefinedExpr *E) { if (DiscardResult) return true; - assert(!Initializing); - return this->visit(E->getFunctionName()); + return this->delegate(E->getFunctionName()); } template @@ -2020,6 +2021,117 @@ bool ByteCodeExprGen::VisitObjCBoolLiteralExpr( return this->emitConst(E->getValue(), E); } +template +bool ByteCodeExprGen::VisitCXXInheritedCtorInitExpr( + const CXXInheritedCtorInitExpr *E) { + const CXXConstructorDecl *Ctor = E->getConstructor(); + assert(!Ctor->isTrivial() && + "Trivial CXXInheritedCtorInitExpr, implement. (possible?)"); + const Function *F = this->getFunction(Ctor); + assert(F); + assert(!F->hasRVO()); + assert(F->hasThisPointer()); + + if (!this->emitDupPtr(SourceInfo{})) + return false; + + // Forward all arguments of the current function (which should be a + // constructor itself) to the inherited ctor. + // This is necessary because the calling code has pushed the pointer + // of the correct base for us already, but the arguments need + // to come after. + unsigned Offset = align(primSize(PT_Ptr)); // instance pointer. + for (const ParmVarDecl *PD : Ctor->parameters()) { + PrimType PT = this->classify(PD->getType()).value_or(PT_Ptr); + + if (!this->emitGetParam(PT, Offset, E)) + return false; + Offset += align(primSize(PT)); + } + + return this->emitCall(F, E); +} + +template +bool ByteCodeExprGen::VisitExpressionTraitExpr( + const ExpressionTraitExpr *E) { + assert(Ctx.getLangOpts().CPlusPlus); + return this->emitConstBool(E->getValue(), E); +} + +template +bool ByteCodeExprGen::VisitCXXUuidofExpr(const CXXUuidofExpr *E) { + if (DiscardResult) + return true; + assert(!Initializing); + + std::optional GlobalIndex = P.getOrCreateGlobal(E->getGuidDecl()); + if (!GlobalIndex) + return false; + if (!this->emitGetPtrGlobal(*GlobalIndex, E)) + return false; + + const Record *R = this->getRecord(E->getType()); + assert(R); + + const APValue &V = E->getGuidDecl()->getAsAPValue(); + if (V.getKind() == APValue::None) + return true; + + assert(V.isStruct()); + assert(V.getStructNumBases() == 0); + // FIXME: This could be useful in visitAPValue, too. + for (unsigned I = 0, N = V.getStructNumFields(); I != N; ++I) { + const APValue &F = V.getStructField(I); + const Record::Field *RF = R->getField(I); + + if (F.isInt()) { + PrimType T = classifyPrim(RF->Decl->getType()); + if (!this->visitAPValue(F, T, E)) + return false; + if (!this->emitInitField(T, RF->Offset, E)) + return false; + } else if (F.isArray()) { + assert(RF->Desc->isPrimitiveArray()); + const auto *ArrType = RF->Decl->getType()->getAsArrayTypeUnsafe(); + PrimType ElemT = classifyPrim(ArrType->getElementType()); + assert(ArrType); + + if (!this->emitDupPtr(E)) + return false; + if (!this->emitGetPtrField(RF->Offset, E)) + return false; + + for (unsigned A = 0, AN = F.getArraySize(); A != AN; ++A) { + if (!this->visitAPValue(F.getArrayInitializedElt(A), ElemT, E)) + return false; + if (!this->emitInitElem(ElemT, A, E)) + return false; + } + + if (!this->emitPopPtr(E)) + return false; + } else { + assert(false && "I don't think this should be possible"); + } + } + + return this->emitInitPtr(E); +} + +template +bool ByteCodeExprGen::VisitRequiresExpr(const RequiresExpr *E) { + assert(classifyPrim(E->getType()) == PT_Bool); + return this->emitConstBool(E->isSatisfied(), E); +} + +template +bool ByteCodeExprGen::VisitConceptSpecializationExpr( + const ConceptSpecializationExpr *E) { + assert(classifyPrim(E->getType()) == PT_Bool); + return this->emitConstBool(E->isSatisfied(), E); +} + template bool ByteCodeExprGen::discard(const Expr *E) { if (E->containsErrors()) return false; @@ -2246,8 +2358,7 @@ bool ByteCodeExprGen::dereferenceParam( const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK, llvm::function_ref Direct, llvm::function_ref Indirect) { - auto It = this->Params.find(PD); - if (It != this->Params.end()) { + if (auto It = this->Params.find(PD); It != this->Params.end()) { unsigned Idx = It->second.Offset; switch (AK) { case DerefKind::Read: @@ -2518,10 +2629,13 @@ bool ByteCodeExprGen::visitExpr(const Expr *E) { // For us, that means everything we don't // have a PrimType for. if (std::optional LocalOffset = this->allocateLocal(E)) { - if (!this->visitLocalInitializer(E, *LocalOffset)) + if (!this->emitGetPtrLocal(*LocalOffset, E)) return false; - if (!this->emitGetPtrLocal(*LocalOffset, E)) + if (!visitInitializer(E)) + return false; + + if (!this->emitInitPtr(E)) return false; return this->emitRetValue(E); } diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 2c9cca5082b121dbdbf6ef0abe1cb045ce71f1f2..eeb56dc845656514c767d54dc6c0ca21ffb8609a 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -111,6 +111,11 @@ public: bool VisitGenericSelectionExpr(const GenericSelectionExpr *E); bool VisitChooseExpr(const ChooseExpr *E); bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E); + bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E); + bool VisitExpressionTraitExpr(const ExpressionTraitExpr *E); + bool VisitCXXUuidofExpr(const CXXUuidofExpr *E); + bool VisitRequiresExpr(const RequiresExpr *E); + bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E); protected: bool visitExpr(const Expr *E) override; diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp index b0ec90a1f2851c49cc991858255c6b99e1d77e7f..bedcc78dc235558e3116759ba114f306bffe695a 100644 --- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -144,6 +144,10 @@ bool ByteCodeStmtGen::visitFunc(const FunctionDecl *F) { auto emitFieldInitializer = [&](const Record::Field *F, unsigned FieldOffset, const Expr *InitExpr) -> bool { + // We don't know what to do with these, so just return false. + if (InitExpr->getType().isNull()) + return false; + if (std::optional T = this->classify(InitExpr)) { if (!this->visit(InitExpr)) return false; diff --git a/clang/lib/AST/Interp/Descriptor.h b/clang/lib/AST/Interp/Descriptor.h index 6cca9d5feedede37947e67527efea9bee4bb624b..6a53205af59926e33ec300c4a3d0e00d1bc1dca7 100644 --- a/clang/lib/AST/Interp/Descriptor.h +++ b/clang/lib/AST/Interp/Descriptor.h @@ -59,17 +59,22 @@ struct InlineDescriptor { /// Flag indicating if the storage is constant or not. /// Relevant for primitive fields. + LLVM_PREFERRED_TYPE(bool) unsigned IsConst : 1; /// For primitive fields, it indicates if the field was initialized. /// Primitive fields in static storage are always initialized. /// Arrays are always initialized, even though their elements might not be. /// Base classes are initialized after the constructor is invoked. + LLVM_PREFERRED_TYPE(bool) unsigned IsInitialized : 1; /// Flag indicating if the field is an embedded base class. + LLVM_PREFERRED_TYPE(bool) unsigned IsBase : 1; /// Flag indicating if the field is the active member of a union. + LLVM_PREFERRED_TYPE(bool) unsigned IsActive : 1; /// Flag indicating if the field is mutable (if in a record). + LLVM_PREFERRED_TYPE(bool) unsigned IsFieldMutable : 1; const Descriptor *Desc; diff --git a/clang/lib/AST/Interp/EvalEmitter.cpp b/clang/lib/AST/Interp/EvalEmitter.cpp index a60f893de8bda7f37d7176279953c0a0bdcea113..945b78d7a609d75a705ffc61fd99f2785e0f04fd 100644 --- a/clang/lib/AST/Interp/EvalEmitter.cpp +++ b/clang/lib/AST/Interp/EvalEmitter.cpp @@ -36,7 +36,7 @@ EvalEmitter::~EvalEmitter() { EvaluationResult EvalEmitter::interpretExpr(const Expr *E) { EvalResult.setSource(E); - if (!this->visitExpr(E)) + if (!this->visitExpr(E) && EvalResult.empty()) EvalResult.setInvalid(); return std::move(this->EvalResult); @@ -45,7 +45,7 @@ EvaluationResult EvalEmitter::interpretExpr(const Expr *E) { EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD) { EvalResult.setSource(VD); - if (!this->visitDecl(VD)) + if (!this->visitDecl(VD) && EvalResult.empty()) EvalResult.setInvalid(); return std::move(this->EvalResult); diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index a76e63395157f75c5f7d2766538df32d1be08853..e2fda18e3f44d45ca2d18f8efc50ebc0397b699a 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -811,7 +811,7 @@ bool CMP3(InterpState &S, CodePtr OpPC, const ComparisonCategoryInfo *CmpInfo) { const auto *CmpValueInfo = CmpInfo->getValueInfo(CmpResult); assert(CmpValueInfo); assert(CmpValueInfo->hasValidIntValue()); - APSInt IntValue = CmpValueInfo->getIntValue(); + const APSInt &IntValue = CmpValueInfo->getIntValue(); return SetThreeWayComparisonField(S, OpPC, P, IntValue); } @@ -1187,15 +1187,18 @@ inline bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I) { /// 2) Pushes Pointer.atField(Off) on the stack inline bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) { const Pointer &Ptr = S.Stk.pop(); + if (S.inConstantContext() && !CheckNull(S, OpPC, Ptr, CSK_Field)) return false; - if (!CheckExtern(S, OpPC, Ptr)) - return false; - if (!CheckRange(S, OpPC, Ptr, CSK_Field)) - return false; - if (!CheckSubobject(S, OpPC, Ptr, CSK_Field)) - return false; + if (CheckDummy(S, OpPC, Ptr)) { + if (!CheckExtern(S, OpPC, Ptr)) + return false; + if (!CheckRange(S, OpPC, Ptr, CSK_Field)) + return false; + if (!CheckSubobject(S, OpPC, Ptr, CSK_Field)) + return false; + } S.Stk.push(Ptr.atField(Off)); return true; } @@ -1278,13 +1281,16 @@ inline bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off) { inline bool InitPtrPop(InterpState &S, CodePtr OpPC) { const Pointer &Ptr = S.Stk.pop(); - Ptr.initialize(); + if (Ptr.canBeInitialized()) + Ptr.initialize(); return true; } inline bool InitPtr(InterpState &S, CodePtr OpPC) { const Pointer &Ptr = S.Stk.peek(); - Ptr.initialize(); + + if (Ptr.canBeInitialized()) + Ptr.initialize(); return true; } @@ -1856,7 +1862,7 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) { const Pointer &Ptr = S.Stk.peek(); if (!CheckDummy(S, OpPC, Ptr)) - return false; + return true; if (!OffsetHelper(S, OpPC, Offset, Ptr)) return false; @@ -1869,8 +1875,10 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) { const T &Offset = S.Stk.pop(); const Pointer &Ptr = S.Stk.pop(); - if (!CheckDummy(S, OpPC, Ptr)) - return false; + if (!CheckDummy(S, OpPC, Ptr)) { + S.Stk.push(Ptr); + return true; + } if (!OffsetHelper(S, OpPC, Offset, Ptr)) return false; @@ -1891,6 +1899,11 @@ inline bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index) { inline bool ArrayDecay(InterpState &S, CodePtr OpPC) { const Pointer &Ptr = S.Stk.pop(); + if (Ptr.isDummy()) { + S.Stk.push(Ptr); + return true; + } + if (!Ptr.isUnknownSizeArray()) { S.Stk.push(Ptr.atIndex(0)); return true; diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index 316a7ed5fa1bb8214009410f6de720b7300992c8..3f85635f43674d1e964f441418d8e77c3d6fc23b 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -83,63 +83,48 @@ void Pointer::operator=(Pointer &&P) { } APValue Pointer::toAPValue() const { - APValue::LValueBase Base; llvm::SmallVector Path; - CharUnits Offset; - bool IsNullPtr; - bool IsOnePastEnd; - - if (isZero()) { - Base = static_cast(nullptr); - IsNullPtr = true; - IsOnePastEnd = false; - Offset = CharUnits::Zero(); - } else { - // Build the lvalue base from the block. - const Descriptor *Desc = getDeclDesc(); - if (auto *VD = Desc->asValueDecl()) - Base = VD; - else if (auto *E = Desc->asExpr()) - Base = E; - else - llvm_unreachable("Invalid allocation type"); - - // Not a null pointer. - IsNullPtr = false; - - if (isUnknownSizeArray()) { - IsOnePastEnd = false; - Offset = CharUnits::Zero(); - } else if (Desc->asExpr()) { - // Pointer pointing to a an expression. - IsOnePastEnd = false; - Offset = CharUnits::Zero(); + + if (isZero()) + return APValue(static_cast(nullptr), CharUnits::Zero(), Path, + /*IsOnePastEnd=*/false, /*IsNullPtr=*/true); + + // Build the lvalue base from the block. + const Descriptor *Desc = getDeclDesc(); + APValue::LValueBase Base; + if (const auto *VD = Desc->asValueDecl()) + Base = VD; + else if (const auto *E = Desc->asExpr()) + Base = E; + else + llvm_unreachable("Invalid allocation type"); + + if (isDummy() || isUnknownSizeArray() || Desc->asExpr()) + return APValue(Base, CharUnits::Zero(), Path, + /*IsOnePastEnd=*/false, /*IsNullPtr=*/false); + + // TODO: compute the offset into the object. + CharUnits Offset = CharUnits::Zero(); + bool IsOnePastEnd = isOnePastEnd(); + + // Build the path into the object. + Pointer Ptr = *this; + while (Ptr.isField() || Ptr.isArrayElement()) { + if (Ptr.isArrayElement()) { + Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getIndex())); + Ptr = Ptr.getArray(); } else { - // TODO: compute the offset into the object. - Offset = CharUnits::Zero(); - - // Build the path into the object. - Pointer Ptr = *this; - while (Ptr.isField() || Ptr.isArrayElement()) { - if (Ptr.isArrayElement()) { - Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getIndex())); - Ptr = Ptr.getArray(); - } else { - // TODO: figure out if base is virtual - bool IsVirtual = false; - - // Create a path entry for the field. - const Descriptor *Desc = Ptr.getFieldDesc(); - if (const auto *BaseOrMember = Desc->asDecl()) { - Path.push_back(APValue::LValuePathEntry({BaseOrMember, IsVirtual})); - Ptr = Ptr.getBase(); - continue; - } - llvm_unreachable("Invalid field type"); - } + // TODO: figure out if base is virtual + bool IsVirtual = false; + + // Create a path entry for the field. + const Descriptor *Desc = Ptr.getFieldDesc(); + if (const auto *BaseOrMember = Desc->asDecl()) { + Path.push_back(APValue::LValuePathEntry({BaseOrMember, IsVirtual})); + Ptr = Ptr.getBase(); + continue; } - - IsOnePastEnd = isOnePastEnd(); + llvm_unreachable("Invalid field type"); } } @@ -149,7 +134,7 @@ APValue Pointer::toAPValue() const { // Just invert the order of the elements. std::reverse(Path.begin(), Path.end()); - return APValue(Base, Offset, Path, IsOnePastEnd, IsNullPtr); + return APValue(Base, Offset, Path, IsOnePastEnd, /*IsNullPtr=*/false); } std::string Pointer::toDiagnosticString(const ASTContext &Ctx) const { @@ -247,11 +232,7 @@ std::optional Pointer::toRValue(const Context &Ctx) const { // Primitive values. if (std::optional T = Ctx.classify(Ty)) { - if (T == PT_Ptr || T == PT_FnPtr) { - R = Ptr.toAPValue(); - } else { - TYPE_SWITCH(*T, R = Ptr.deref().toAPValue()); - } + TYPE_SWITCH(*T, R = Ptr.deref().toAPValue()); return true; } diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index b2b478af2e73116616b490bf7d04deb6692363f3..964c0377c6dc1fc3b38e04b48e2bfe5cc3aab615 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -169,7 +169,7 @@ std::optional Program::createGlobal(const ValueDecl *VD, if (const auto *Var = dyn_cast(VD)) { IsStatic = Context::shouldBeGloballyIndexed(VD); IsExtern = !Var->getAnyInitializer(); - } else if (isa(VD)) { + } else if (isa(VD)) { IsStatic = true; IsExtern = false; } else { diff --git a/clang/lib/AST/Interp/Program.h b/clang/lib/AST/Interp/Program.h index 17342680102cffb52e0018a94e5f824ebb96cc27..364a63dbf477a7f6e8acce16dff52f558757b6cc 100644 --- a/clang/lib/AST/Interp/Program.h +++ b/clang/lib/AST/Interp/Program.h @@ -86,7 +86,7 @@ public: std::optional getOrCreateDummy(const ValueDecl *VD); /// Creates a global and returns its index. - std::optional createGlobal(const ValueDecl *VD, const Expr *E); + std::optional createGlobal(const ValueDecl *VD, const Expr *Init); /// Creates a global from a lifetime-extended temporary. std::optional createGlobal(const Expr *E); diff --git a/clang/lib/AST/Linkage.h b/clang/lib/AST/Linkage.h index 31f384eb75d0b2e70ab011aa3c3588bfc818e3e0..e4dcb5e53261ce875675ce7026eca8c4677017e8 100644 --- a/clang/lib/AST/Linkage.h +++ b/clang/lib/AST/Linkage.h @@ -29,12 +29,15 @@ namespace clang { struct LVComputationKind { /// The kind of entity whose visibility is ultimately being computed; /// visibility computations for types and non-types follow different rules. + LLVM_PREFERRED_TYPE(bool) unsigned ExplicitKind : 1; /// Whether explicit visibility attributes should be ignored. When set, /// visibility may only be restricted by the visibility of template arguments. + LLVM_PREFERRED_TYPE(bool) unsigned IgnoreExplicitVisibility : 1; /// Whether all visibility should be ignored. When set, we're only interested /// in computing linkage. + LLVM_PREFERRED_TYPE(bool) unsigned IgnoreAllVisibility : 1; enum { NumLVComputationKindBits = 3 }; diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 6dfaadd92e79730aff49051966f64d700a0f12fa..a3b7431f7ffd6dc134cc4a58f9ec78b0498fca67 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -602,21 +602,28 @@ protected: /// Whether the external AST source has provided a layout for this /// record. + LLVM_PREFERRED_TYPE(bool) unsigned UseExternalLayout : 1; /// Whether we need to infer alignment, even when we have an /// externally-provided layout. + LLVM_PREFERRED_TYPE(bool) unsigned InferAlignment : 1; /// Packed - Whether the record is packed or not. + LLVM_PREFERRED_TYPE(bool) unsigned Packed : 1; + LLVM_PREFERRED_TYPE(bool) unsigned IsUnion : 1; + LLVM_PREFERRED_TYPE(bool) unsigned IsMac68kAlign : 1; + LLVM_PREFERRED_TYPE(bool) unsigned IsNaturalAlign : 1; + LLVM_PREFERRED_TYPE(bool) unsigned IsMsStruct : 1; /// UnfilledBitsInLastUnit - If the last field laid out was a bitfield, diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index afd05881cb162107501d372bbfbaeb5a6e1d1a8a..fe59d6070b3e811917336a855399df209451eac9 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -23,6 +23,7 @@ #include "clang/AST/ExprOpenMP.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" #include "clang/AST/Type.h" #include "clang/Basic/CharInfo.h" diff --git a/clang/lib/AST/StmtOpenACC.cpp b/clang/lib/AST/StmtOpenACC.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a99c246381839cbd1b025efedc34eb52a6e7aa1 --- /dev/null +++ b/clang/lib/AST/StmtOpenACC.cpp @@ -0,0 +1,33 @@ +//===--- StmtOpenACC.cpp - Classes for OpenACC Constructs -----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the subclesses of Stmt class declared in StmtOpenACC.h +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/StmtOpenACC.h" +#include "clang/AST/ASTContext.h" +using namespace clang; + +OpenACCComputeConstruct * +OpenACCComputeConstruct::CreateEmpty(const ASTContext &C, EmptyShell) { + void *Mem = C.Allocate(sizeof(OpenACCComputeConstruct), + alignof(OpenACCComputeConstruct)); + auto *Inst = new (Mem) OpenACCComputeConstruct; + return Inst; +} + +OpenACCComputeConstruct * +OpenACCComputeConstruct::Create(const ASTContext &C, OpenACCDirectiveKind K, + SourceLocation BeginLoc, + SourceLocation EndLoc) { + void *Mem = C.Allocate(sizeof(OpenACCComputeConstruct), + alignof(OpenACCComputeConstruct)); + auto *Inst = new (Mem) OpenACCComputeConstruct(K, BeginLoc, EndLoc); + return Inst; +} diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 1df040e06db35e91ad6c7d519074521357aa70bd..d66c3ccce2094c47affed4e534640fe571dfdc0e 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1137,6 +1137,15 @@ void StmtPrinter::VisitOMPTargetParallelGenericLoopDirective( PrintOMPExecutableDirective(Node); } +//===----------------------------------------------------------------------===// +// OpenACC construct printing methods +//===----------------------------------------------------------------------===// +void StmtPrinter::VisitOpenACCComputeConstruct(OpenACCComputeConstruct *S) { + Indent() << "#pragma acc " << S->getDirectiveKind(); + // TODO OpenACC: Print Clauses. + PrintStmt(S->getStructuredBlock()); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 1b817cf58b999d5264ac89b9873b96055bf397b1..b545ff472e5a2b81ebc30e7fdc63c549b3975e62 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2441,6 +2441,13 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { } } +void StmtProfiler::VisitOpenACCComputeConstruct( + const OpenACCComputeConstruct *S) { + // VisitStmt handles children, so the AssociatedStmt is handled. + VisitStmt(S); + // TODO OpenACC: Visit Clauses. +} + void Stmt::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr) const { StmtProfilerWithPointers Profiler(ID, Context, Canonical, ProfileLambdaExpr); diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 0000d26dd49eb2d900b899c8e38fe6483df03063..b683eb1edd8f136eb9c878ce995a635f1685a721 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -2668,3 +2668,8 @@ void TextNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) { OS << " tbuffer"; dumpName(D); } + +void TextNodeDumper::VisitOpenACCConstructStmt(const OpenACCConstructStmt *S) { + OS << " " << S->getDirectiveKind(); + // TODO OpenACC: Dump clauses as well. +} diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 24811ded970e81d332326e33bb1ab3cf5ebfed7d..d487944ce92111ea3c332c2bf1c7d96f07b56977 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -887,34 +887,10 @@ Value *Environment::createValueUnlessSelfReferential( if (Type->isRecordType()) { CreatedValuesCount++; - llvm::DenseMap FieldLocs; - for (const FieldDecl *Field : DACtx->getModeledFields(Type)) { - assert(Field != nullptr); + auto &Loc = cast(createStorageLocation(Type)); + initializeFieldsWithValues(Loc, Visited, Depth, CreatedValuesCount); - QualType FieldType = Field->getType(); - - FieldLocs.insert( - {Field, &createLocAndMaybeValue(FieldType, Visited, Depth + 1, - CreatedValuesCount)}); - } - - RecordStorageLocation::SyntheticFieldMap SyntheticFieldLocs; - for (const auto &Entry : DACtx->getSyntheticFields(Type)) { - SyntheticFieldLocs.insert( - {Entry.getKey(), - &createLocAndMaybeValue(Entry.getValue(), Visited, Depth + 1, - CreatedValuesCount)}); - } - - RecordStorageLocation &Loc = DACtx->createRecordStorageLocation( - Type, std::move(FieldLocs), std::move(SyntheticFieldLocs)); - RecordValue &RecordVal = create(Loc); - - // As we already have a storage location for the `RecordValue`, we can and - // should associate them in the environment. - setValue(Loc, RecordVal); - - return &RecordVal; + return &refreshRecordValue(Loc, *this); } return nullptr; @@ -943,6 +919,50 @@ Environment::createLocAndMaybeValue(QualType Ty, return Loc; } +void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc, + llvm::DenseSet &Visited, + int Depth, + int &CreatedValuesCount) { + auto initField = [&](QualType FieldType, StorageLocation &FieldLoc) { + if (FieldType->isRecordType()) { + auto &FieldRecordLoc = cast(FieldLoc); + setValue(FieldRecordLoc, create(FieldRecordLoc)); + initializeFieldsWithValues(FieldRecordLoc, Visited, Depth + 1, + CreatedValuesCount); + } else { + if (!Visited.insert(FieldType.getCanonicalType()).second) + return; + if (Value *Val = createValueUnlessSelfReferential( + FieldType, Visited, Depth + 1, CreatedValuesCount)) + setValue(FieldLoc, *Val); + Visited.erase(FieldType.getCanonicalType()); + } + }; + + for (const auto &[Field, FieldLoc] : Loc.children()) { + assert(Field != nullptr); + QualType FieldType = Field->getType(); + + if (FieldType->isReferenceType()) { + Loc.setChild(*Field, + &createLocAndMaybeValue(FieldType, Visited, Depth + 1, + CreatedValuesCount)); + } else { + assert(FieldLoc != nullptr); + initField(FieldType, *FieldLoc); + } + } + for (const auto &[FieldName, FieldLoc] : Loc.synthetic_fields()) { + assert(FieldLoc != nullptr); + QualType FieldType = FieldLoc->getType(); + + // Synthetic fields cannot have reference type, so we don't need to deal + // with this case. + assert(!FieldType->isReferenceType()); + initField(FieldType, Loc.getSyntheticField(FieldName)); + } +} + StorageLocation &Environment::createObjectInternal(const ValueDecl *D, QualType Ty, const Expr *InitExpr) { diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index bb3aec763c29ca22df7eae373daae198354cb17b..f0b15f43b1f42319435872363dd5a3d8e799cffe 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -535,7 +535,19 @@ public: return; copyRecord(*LocSrc, *LocDst, Env); - Env.setStorageLocation(*S, *LocDst); + + // If the expr is a glvalue, we can reasonably assume the operator is + // returning T& and thus we can assign it `LocDst`. + if (S->isGLValue()) { + Env.setStorageLocation(*S, *LocDst); + } else if (S->getType()->isRecordType()) { + // Make sure that we have a `RecordValue` for this expression so that + // `Environment::getResultObjectLocation()` is able to return a location + // for it. + if (Env.getValue(*S) == nullptr) + refreshRecordValue(*S, Env); + } + return; } @@ -545,6 +557,10 @@ public: VisitCallExpr(S); } + void VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *RBO) { + propagateValue(*RBO->getSemanticForm(), *RBO, Env); + } + void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) { if (S->getCastKind() == CK_ConstructorConversion) { const Expr *SubExpr = S->getSubExpr(); diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index a6dcf16b928e262a7d4d93cefe38d77dfc12450a..3c2a6fd81b1d8ff0129c9c8b30a1a473fbc81eee 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -12,10 +12,14 @@ #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" #include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" #include #include #include @@ -407,9 +411,6 @@ using DeclUseList = SmallVector; // Convenience typedef. using FixItList = SmallVector; - -// Defined below. -class Strategy; } // namespace namespace { @@ -486,7 +487,7 @@ public: /// Returns a fixit that would fix the current gadget according to /// the current strategy. Returns std::nullopt if the fix cannot be produced; /// returns an empty list if no fixes are necessary. - virtual std::optional getFixits(const Strategy &) const { + virtual std::optional getFixits(const FixitStrategy &) const { return std::nullopt; } @@ -737,7 +738,8 @@ public: return stmt(PtrInitStmt); } - virtual std::optional getFixits(const Strategy &S) const override; + 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 @@ -789,7 +791,8 @@ public: return stmt(isInUnspecifiedUntypedContext(PtrAssignExpr)); } - virtual std::optional getFixits(const Strategy &S) const override; + 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 @@ -892,7 +895,8 @@ public: return expr(isInUnspecifiedLvalueContext(Target)); } - virtual std::optional getFixits(const Strategy &S) const override; + virtual std::optional + getFixits(const FixitStrategy &S) const override; virtual const Stmt *getBaseStmt() const override { return Node; } @@ -932,7 +936,8 @@ public: return stmt(isInUnspecifiedPointerContext(target)); } - virtual std::optional getFixits(const Strategy &S) const override; + virtual std::optional + getFixits(const FixitStrategy &S) const override; virtual const Stmt *getBaseStmt() const override { return Node; } @@ -976,7 +981,8 @@ public: virtual const Stmt *getBaseStmt() const final { return Op; } - virtual std::optional getFixits(const Strategy &S) const override; + virtual std::optional + getFixits(const FixitStrategy &S) const override; }; // Represents expressions of the form `&DRE[any]` in the Unspecified Pointer @@ -1009,7 +1015,8 @@ public: .bind(UPCAddressofArraySubscriptTag))))); } - virtual std::optional getFixits(const Strategy &) const override; + virtual std::optional + getFixits(const FixitStrategy &) const override; virtual const Stmt *getBaseStmt() const override { return Node; } @@ -1088,46 +1095,6 @@ public: }; } // namespace -namespace { -// Strategy is a map from variables to the way we plan to emit fixes for -// these variables. It is figured out gradually by trying different fixes -// for different variables depending on gadgets in which these variables -// participate. -class Strategy { -public: - enum class Kind { - Wontfix, // We don't plan to emit a fixit for this variable. - Span, // We recommend replacing the variable with std::span. - Iterator, // We recommend replacing the variable with std::span::iterator. - Array, // We recommend replacing the variable with std::array. - Vector // We recommend replacing the variable with std::vector. - }; - -private: - using MapTy = llvm::DenseMap; - - MapTy Map; - -public: - Strategy() = default; - Strategy(const Strategy &) = delete; // Let's avoid copies. - Strategy &operator=(const Strategy &) = delete; - Strategy(Strategy &&) = default; - Strategy &operator=(Strategy &&) = default; - - void set(const VarDecl *VD, Kind K) { Map[VD] = K; } - - Kind lookup(const VarDecl *VD) const { - auto I = Map.find(VD); - if (I == Map.end()) - return Kind::Wontfix; - - return I->second; - } -}; -} // namespace - - // Representing a pointer type expression of the form `++Ptr` in an Unspecified // Pointer Context (UPC): class UPCPreIncrementGadget : public FixableGadget { @@ -1159,7 +1126,8 @@ public: ).bind(UPCPreIncrementTag))))); } - virtual std::optional getFixits(const Strategy &S) const override; + virtual std::optional + getFixits(const FixitStrategy &S) const override; virtual const Stmt *getBaseStmt() const override { return Node; } @@ -1204,7 +1172,8 @@ public: // clang-format on } - virtual std::optional getFixits(const Strategy &S) const override; + virtual std::optional + getFixits(const FixitStrategy &S) const override; virtual const Stmt *getBaseStmt() const override { return Node; } @@ -1254,7 +1223,8 @@ public: // clang-format on } - virtual std::optional getFixits(const Strategy &s) const final; + virtual std::optional + getFixits(const FixitStrategy &s) const final; // TODO remove this method from FixableGadget interface virtual const Stmt *getBaseStmt() const final { return nullptr; } @@ -1464,38 +1434,40 @@ bool clang::internal::anyConflict(const SmallVectorImpl &FixIts, } std::optional -PointerAssignmentGadget::getFixits(const Strategy &S) const { +PointerAssignmentGadget::getFixits(const FixitStrategy &S) const { const auto *LeftVD = cast(PtrLHS->getDecl()); const auto *RightVD = cast(PtrRHS->getDecl()); switch (S.lookup(LeftVD)) { - case Strategy::Kind::Span: - if (S.lookup(RightVD) == Strategy::Kind::Span) - return FixItList{}; - return std::nullopt; - case Strategy::Kind::Wontfix: - return std::nullopt; - case Strategy::Kind::Iterator: - case Strategy::Kind::Array: - case Strategy::Kind::Vector: - llvm_unreachable("unsupported strategies for FixableGadgets"); + case FixitStrategy::Kind::Span: + if (S.lookup(RightVD) == FixitStrategy::Kind::Span) + return FixItList{}; + return std::nullopt; + case FixitStrategy::Kind::Wontfix: + return std::nullopt; + case FixitStrategy::Kind::Iterator: + case FixitStrategy::Kind::Array: + return std::nullopt; + case FixitStrategy::Kind::Vector: + llvm_unreachable("unsupported strategies for FixableGadgets"); } return std::nullopt; } std::optional -PointerInitGadget::getFixits(const Strategy &S) const { +PointerInitGadget::getFixits(const FixitStrategy &S) const { const auto *LeftVD = PtrInitLHS; const auto *RightVD = cast(PtrInitRHS->getDecl()); switch (S.lookup(LeftVD)) { - case Strategy::Kind::Span: - if (S.lookup(RightVD) == Strategy::Kind::Span) - return FixItList{}; - return std::nullopt; - case Strategy::Kind::Wontfix: - return std::nullopt; - case Strategy::Kind::Iterator: - case Strategy::Kind::Array: - case Strategy::Kind::Vector: + case FixitStrategy::Kind::Span: + if (S.lookup(RightVD) == FixitStrategy::Kind::Span) + return FixItList{}; + return std::nullopt; + case FixitStrategy::Kind::Wontfix: + return std::nullopt; + case FixitStrategy::Kind::Iterator: + case FixitStrategy::Kind::Array: + return std::nullopt; + case FixitStrategy::Kind::Vector: llvm_unreachable("unsupported strategies for FixableGadgets"); } return std::nullopt; @@ -1512,12 +1484,12 @@ static bool isNonNegativeIntegerExpr(const Expr *Expr, const VarDecl *VD, } std::optional -ULCArraySubscriptGadget::getFixits(const Strategy &S) const { +ULCArraySubscriptGadget::getFixits(const FixitStrategy &S) const { if (const auto *DRE = dyn_cast(Node->getBase()->IgnoreImpCasts())) if (const auto *VD = dyn_cast(DRE->getDecl())) { switch (S.lookup(VD)) { - case Strategy::Kind::Span: { + case FixitStrategy::Kind::Span: { // If the index has a negative constant value, we give up as no valid // fix-it can be generated: @@ -1528,10 +1500,11 @@ ULCArraySubscriptGadget::getFixits(const Strategy &S) const { // no-op is a good fix-it, otherwise return FixItList{}; } - case Strategy::Kind::Wontfix: - case Strategy::Kind::Iterator: - case Strategy::Kind::Array: - case Strategy::Kind::Vector: + case FixitStrategy::Kind::Array: + return FixItList{}; + case FixitStrategy::Kind::Wontfix: + case FixitStrategy::Kind::Iterator: + case FixitStrategy::Kind::Vector: llvm_unreachable("unsupported strategies for FixableGadgets"); } } @@ -1542,17 +1515,18 @@ static std::optional // forward declaration fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node); std::optional -UPCAddressofArraySubscriptGadget::getFixits(const Strategy &S) const { +UPCAddressofArraySubscriptGadget::getFixits(const FixitStrategy &S) const { auto DREs = getClaimedVarUseSites(); const auto *VD = cast(DREs.front()->getDecl()); switch (S.lookup(VD)) { - case Strategy::Kind::Span: + case FixitStrategy::Kind::Span: return fixUPCAddressofArraySubscriptWithSpan(Node); - case Strategy::Kind::Wontfix: - case Strategy::Kind::Iterator: - case Strategy::Kind::Array: - case Strategy::Kind::Vector: + case FixitStrategy::Kind::Wontfix: + case FixitStrategy::Kind::Iterator: + case FixitStrategy::Kind::Array: + return std::nullopt; + case FixitStrategy::Kind::Vector: llvm_unreachable("unsupported strategies for FixableGadgets"); } return std::nullopt; // something went wrong, no fix-it @@ -1803,10 +1777,10 @@ getSpanTypeText(StringRef EltTyText, } std::optional -DerefSimplePtrArithFixableGadget::getFixits(const Strategy &s) const { +DerefSimplePtrArithFixableGadget::getFixits(const FixitStrategy &s) const { const VarDecl *VD = dyn_cast(BaseDeclRefExpr->getDecl()); - if (VD && s.lookup(VD) == Strategy::Kind::Span) { + if (VD && s.lookup(VD) == FixitStrategy::Kind::Span) { ASTContext &Ctx = VD->getASTContext(); // std::span can't represent elements before its begin() if (auto ConstVal = Offset->getIntegerConstantExpr(Ctx)) @@ -1866,10 +1840,10 @@ DerefSimplePtrArithFixableGadget::getFixits(const Strategy &s) const { } std::optional -PointerDereferenceGadget::getFixits(const Strategy &S) const { +PointerDereferenceGadget::getFixits(const FixitStrategy &S) const { const VarDecl *VD = cast(BaseDeclRefExpr->getDecl()); switch (S.lookup(VD)) { - case Strategy::Kind::Span: { + case FixitStrategy::Kind::Span: { ASTContext &Ctx = VD->getASTContext(); SourceManager &SM = Ctx.getSourceManager(); // Required changes: *(ptr); => (ptr[0]); and *ptr; => ptr[0] @@ -1884,11 +1858,12 @@ PointerDereferenceGadget::getFixits(const Strategy &S) const { } break; } - case Strategy::Kind::Iterator: - case Strategy::Kind::Array: - case Strategy::Kind::Vector: - llvm_unreachable("Strategy not implemented yet!"); - case Strategy::Kind::Wontfix: + case FixitStrategy::Kind::Iterator: + case FixitStrategy::Kind::Array: + return std::nullopt; + case FixitStrategy::Kind::Vector: + llvm_unreachable("FixitStrategy not implemented yet!"); + case FixitStrategy::Kind::Wontfix: llvm_unreachable("Invalid strategy!"); } @@ -1897,28 +1872,28 @@ PointerDereferenceGadget::getFixits(const Strategy &S) const { // Generates fix-its replacing an expression of the form UPC(DRE) with // `DRE.data()` -std::optional UPCStandalonePointerGadget::getFixits(const Strategy &S) - const { +std::optional +UPCStandalonePointerGadget::getFixits(const FixitStrategy &S) const { const auto VD = cast(Node->getDecl()); switch (S.lookup(VD)) { - case Strategy::Kind::Span: { - ASTContext &Ctx = VD->getASTContext(); - SourceManager &SM = Ctx.getSourceManager(); - // Inserts the .data() after the DRE - std::optional EndOfOperand = - getPastLoc(Node, SM, Ctx.getLangOpts()); - - if (EndOfOperand) - return FixItList{{FixItHint::CreateInsertion( - *EndOfOperand, ".data()")}}; - // FIXME: Points inside a macro expansion. - break; - } - case Strategy::Kind::Wontfix: - case Strategy::Kind::Iterator: - case Strategy::Kind::Array: - case Strategy::Kind::Vector: - llvm_unreachable("unsupported strategies for FixableGadgets"); + case FixitStrategy::Kind::Span: { + ASTContext &Ctx = VD->getASTContext(); + SourceManager &SM = Ctx.getSourceManager(); + // Inserts the .data() after the DRE + std::optional EndOfOperand = + getPastLoc(Node, SM, Ctx.getLangOpts()); + + if (EndOfOperand) + return FixItList{{FixItHint::CreateInsertion(*EndOfOperand, ".data()")}}; + // FIXME: Points inside a macro expansion. + break; + } + case FixitStrategy::Kind::Wontfix: + case FixitStrategy::Kind::Iterator: + case FixitStrategy::Kind::Array: + return std::nullopt; + case FixitStrategy::Kind::Vector: + llvm_unreachable("unsupported strategies for FixableGadgets"); } return std::nullopt; @@ -1962,14 +1937,14 @@ fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node) { } std::optional -UUCAddAssignGadget::getFixits(const Strategy &S) const { +UUCAddAssignGadget::getFixits(const FixitStrategy &S) const { DeclUseList DREs = getClaimedVarUseSites(); if (DREs.size() != 1) return std::nullopt; // In cases of `Ptr += n` where `Ptr` is not a DRE, we // give up if (const VarDecl *VD = dyn_cast(DREs.front()->getDecl())) { - if (S.lookup(VD) == Strategy::Kind::Span) { + if (S.lookup(VD) == FixitStrategy::Kind::Span) { FixItList Fixes; const Stmt *AddAssignNode = getBaseStmt(); @@ -2003,14 +1978,15 @@ UUCAddAssignGadget::getFixits(const Strategy &S) const { return std::nullopt; // Not in the cases that we can handle for now, give up. } -std::optional UPCPreIncrementGadget::getFixits(const Strategy &S) const { +std::optional +UPCPreIncrementGadget::getFixits(const FixitStrategy &S) const { DeclUseList DREs = getClaimedVarUseSites(); if (DREs.size() != 1) return std::nullopt; // In cases of `++Ptr` where `Ptr` is not a DRE, we // give up if (const VarDecl *VD = dyn_cast(DREs.front()->getDecl())) { - if (S.lookup(VD) == Strategy::Kind::Span) { + if (S.lookup(VD) == FixitStrategy::Kind::Span) { FixItList Fixes; std::stringstream SS; const Stmt *PreIncNode = getBaseStmt(); @@ -2033,7 +2009,6 @@ std::optional UPCPreIncrementGadget::getFixits(const Strategy &S) con return std::nullopt; // Not in the cases that we can handle for now, give up. } - // For a non-null initializer `Init` of `T *` type, this function returns // `FixItHint`s producing a list initializer `{Init, S}` as a part of a fix-it // to output stream. @@ -2261,7 +2236,7 @@ static bool hasConflictingOverload(const FunctionDecl *FD) { // } // static std::optional -createOverloadsForFixedParams(const Strategy &S, const FunctionDecl *FD, +createOverloadsForFixedParams(const FixitStrategy &S, const FunctionDecl *FD, const ASTContext &Ctx, UnsafeBufferUsageHandler &Handler) { // FIXME: need to make this conflict checking better: @@ -2278,9 +2253,9 @@ createOverloadsForFixedParams(const Strategy &S, const FunctionDecl *FD, for (unsigned i = 0; i < NumParms; i++) { const ParmVarDecl *PVD = FD->getParamDecl(i); - if (S.lookup(PVD) == Strategy::Kind::Wontfix) + if (S.lookup(PVD) == FixitStrategy::Kind::Wontfix) continue; - if (S.lookup(PVD) != Strategy::Kind::Span) + if (S.lookup(PVD) != FixitStrategy::Kind::Span) // Not supported, not suppose to happen: return std::nullopt; @@ -2291,7 +2266,8 @@ createOverloadsForFixedParams(const Strategy &S, const FunctionDecl *FD, if (!PteTyText) // something wrong in obtaining the text of the pointee type, give up return std::nullopt; - // FIXME: whether we should create std::span type depends on the Strategy. + // FIXME: whether we should create std::span type depends on the + // FixitStrategy. NewTysTexts[i] = getSpanTypeText(*PteTyText, PteTyQuals); ParmsMask[i] = true; AtLeastOneParmToFix = true; @@ -2495,10 +2471,103 @@ static FixItList fixVariableWithSpan(const VarDecl *VD, return fixLocalVarDeclWithSpan(VD, Ctx, getUserFillPlaceHolder(), Handler); } +static FixItList fixVarDeclWithArray(const VarDecl *D, const ASTContext &Ctx, + UnsafeBufferUsageHandler &Handler) { + FixItList FixIts{}; + + // Note: the code below expects the declaration to not use any type sugar like + // typedef. + if (auto CAT = dyn_cast(D->getType())) { + const QualType &ArrayEltT = CAT->getElementType(); + assert(!ArrayEltT.isNull() && "Trying to fix a non-array type variable!"); + // FIXME: support multi-dimensional arrays + if (isa(ArrayEltT.getCanonicalType())) + return {}; + + const SourceLocation IdentifierLoc = getVarDeclIdentifierLoc(D); + + // Get the spelling of the element type as written in the source file + // (including macros, etc.). + auto MaybeElemTypeTxt = + getRangeText({D->getBeginLoc(), IdentifierLoc}, Ctx.getSourceManager(), + Ctx.getLangOpts()); + if (!MaybeElemTypeTxt) + return {}; + const llvm::StringRef ElemTypeTxt = MaybeElemTypeTxt->trim(); + + // Find the '[' token. + std::optional NextTok = Lexer::findNextToken( + IdentifierLoc, Ctx.getSourceManager(), Ctx.getLangOpts()); + while (NextTok && !NextTok->is(tok::l_square) && + NextTok->getLocation() <= D->getSourceRange().getEnd()) + NextTok = Lexer::findNextToken(NextTok->getLocation(), + Ctx.getSourceManager(), Ctx.getLangOpts()); + if (!NextTok) + return {}; + const SourceLocation LSqBracketLoc = NextTok->getLocation(); + + // Get the spelling of the array size as written in the source file + // (including macros, etc.). + auto MaybeArraySizeTxt = getRangeText( + {LSqBracketLoc.getLocWithOffset(1), D->getTypeSpecEndLoc()}, + Ctx.getSourceManager(), Ctx.getLangOpts()); + if (!MaybeArraySizeTxt) + return {}; + const llvm::StringRef ArraySizeTxt = MaybeArraySizeTxt->trim(); + if (ArraySizeTxt.empty()) { + // FIXME: Support array size getting determined from the initializer. + // Examples: + // int arr1[] = {0, 1, 2}; + // int arr2{3, 4, 5}; + // We might be able to preserve the non-specified size with `auto` and + // `std::to_array`: + // auto arr1 = std::to_array({0, 1, 2}); + return {}; + } + + std::optional IdentText = + getVarDeclIdentifierText(D, Ctx.getSourceManager(), Ctx.getLangOpts()); + + if (!IdentText) { + DEBUG_NOTE_DECL_FAIL(D, " : failed to locate the identifier"); + return {}; + } + + SmallString<32> Replacement; + raw_svector_ostream OS(Replacement); + OS << "std::array<" << ElemTypeTxt << ", " << ArraySizeTxt << "> " + << IdentText->str(); + + FixIts.push_back(FixItHint::CreateReplacement( + SourceRange{D->getBeginLoc(), D->getTypeSpecEndLoc()}, OS.str())); + } + + return FixIts; +} + +static FixItList fixVariableWithArray(const VarDecl *VD, + const DeclUseTracker &Tracker, + const ASTContext &Ctx, + UnsafeBufferUsageHandler &Handler) { + const DeclStmt *DS = Tracker.lookupDecl(VD); + assert(DS && "Fixing non-local variables not implemented yet!"); + if (!DS->isSingleDecl()) { + // FIXME: to support handling multiple `VarDecl`s in a single `DeclStmt` + return {}; + } + // Currently DS is an unused variable but we'll need it when + // non-single decls are implemented, where the pointee type name + // and the '*' are spread around the place. + (void)DS; + + // FIXME: handle cases where DS has multiple declarations + return fixVarDeclWithArray(VD, Ctx, Handler); +} + // TODO: we should be consistent to use `std::nullopt` to represent no-fix due // to any unexpected problem. static FixItList -fixVariable(const VarDecl *VD, Strategy::Kind K, +fixVariable(const VarDecl *VD, FixitStrategy::Kind K, /* The function decl under analysis */ const Decl *D, const DeclUseTracker &Tracker, ASTContext &Ctx, UnsafeBufferUsageHandler &Handler) { @@ -2529,7 +2598,7 @@ fixVariable(const VarDecl *VD, Strategy::Kind K, } switch (K) { - case Strategy::Kind::Span: { + case FixitStrategy::Kind::Span: { if (VD->getType()->isPointerType()) { if (const auto *PVD = dyn_cast(VD)) return fixParamWithSpan(PVD, Ctx, Handler); @@ -2540,11 +2609,18 @@ fixVariable(const VarDecl *VD, Strategy::Kind K, DEBUG_NOTE_DECL_FAIL(VD, " : not a pointer"); return {}; } - case Strategy::Kind::Iterator: - case Strategy::Kind::Array: - case Strategy::Kind::Vector: - llvm_unreachable("Strategy not implemented yet!"); - case Strategy::Kind::Wontfix: + case FixitStrategy::Kind::Array: { + if (VD->isLocalVarDecl() && + isa(VD->getType().getCanonicalType())) + return fixVariableWithArray(VD, Tracker, Ctx, Handler); + + DEBUG_NOTE_DECL_FAIL(VD, " : not a local const-size array"); + return {}; + } + case FixitStrategy::Kind::Iterator: + case FixitStrategy::Kind::Vector: + llvm_unreachable("FixitStrategy not implemented yet!"); + case FixitStrategy::Kind::Wontfix: llvm_unreachable("Invalid strategy!"); } llvm_unreachable("Unknown strategy!"); @@ -2605,7 +2681,8 @@ static void eraseVarsForUnfixableGroupMates( static FixItList createFunctionOverloadsForParms( std::map &FixItsForVariable /* mutable */, const VariableGroupsManager &VarGrpMgr, const FunctionDecl *FD, - const Strategy &S, ASTContext &Ctx, UnsafeBufferUsageHandler &Handler) { + const FixitStrategy &S, ASTContext &Ctx, + UnsafeBufferUsageHandler &Handler) { FixItList FixItsSharedByParms{}; std::optional OverloadFixes = @@ -2625,8 +2702,8 @@ static FixItList createFunctionOverloadsForParms( // Constructs self-contained fix-its for each variable in `FixablesForAllVars`. static std::map -getFixIts(FixableGadgetSets &FixablesForAllVars, const Strategy &S, - ASTContext &Ctx, +getFixIts(FixableGadgetSets &FixablesForAllVars, const FixitStrategy &S, + ASTContext &Ctx, /* The function decl under analysis */ const Decl *D, const DeclUseTracker &Tracker, UnsafeBufferUsageHandler &Handler, const VariableGroupsManager &VarGrpMgr) { @@ -2724,11 +2801,14 @@ getFixIts(FixableGadgetSets &FixablesForAllVars, const Strategy &S, } template -static Strategy +static FixitStrategy getNaiveStrategy(llvm::iterator_range UnsafeVars) { - Strategy S; + FixitStrategy S; for (const VarDecl *VD : UnsafeVars) { - S.set(VD, Strategy::Kind::Span); + if (isa(VD->getType().getCanonicalType())) + S.set(VD, FixitStrategy::Kind::Array); + else + S.set(VD, FixitStrategy::Kind::Span); } return S; } @@ -3034,7 +3114,7 @@ void clang::checkUnsafeBufferUsage(const Decl *D, // We assign strategies to variables that are 1) in the graph and 2) can be // fixed. Other variables have the default "Won't fix" strategy. - Strategy NaiveStrategy = getNaiveStrategy(llvm::make_filter_range( + FixitStrategy NaiveStrategy = getNaiveStrategy(llvm::make_filter_range( VisitedVars, [&FixablesForAllVars](const VarDecl *V) { // If a warned variable has no "Fixable", it is considered unfixable: return FixablesForAllVars.byVar.count(V); @@ -3057,9 +3137,9 @@ void clang::checkUnsafeBufferUsage(const Decl *D, auto FixItsIt = FixItsForVariableGroup.find(VD); Handler.handleUnsafeVariableGroup(VD, VarGrpMgr, FixItsIt != FixItsForVariableGroup.end() - ? std::move(FixItsIt->second) - : FixItList{}, - D); + ? std::move(FixItsIt->second) + : FixItList{}, + D, NaiveStrategy); for (const auto &G : WarningGadgets) { Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/true, D->getASTContext()); diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp index 6c7bd50eefb7ef618ce8df9b175aa2f13d6ade1c..b353a6627f298bae566e27b2b8edfccca2449d76 100644 --- a/clang/lib/Basic/DiagnosticIDs.cpp +++ b/clang/lib/Basic/DiagnosticIDs.cpp @@ -100,7 +100,7 @@ const uint32_t StaticDiagInfoDescriptionOffsets[] = { }; // Diagnostic classes. -enum { +enum DiagnosticClass { CLASS_NOTE = 0x01, CLASS_REMARK = 0x02, CLASS_WARNING = 0x03, @@ -110,15 +110,22 @@ enum { struct StaticDiagInfoRec { uint16_t DiagID; + LLVM_PREFERRED_TYPE(diag::Severity) uint8_t DefaultSeverity : 3; + LLVM_PREFERRED_TYPE(DiagnosticClass) uint8_t Class : 3; + LLVM_PREFERRED_TYPE(DiagnosticIDs::SFINAEResponse) uint8_t SFINAE : 2; uint8_t Category : 6; + LLVM_PREFERRED_TYPE(bool) uint8_t WarnNoWerror : 1; + LLVM_PREFERRED_TYPE(bool) uint8_t WarnShowInSystemHeader : 1; + LLVM_PREFERRED_TYPE(bool) uint8_t WarnShowInSystemMacro : 1; uint16_t OptionGroupIndex : 15; + LLVM_PREFERRED_TYPE(bool) uint16_t Deferrable : 1; uint16_t DescriptionLen; diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index 925217431d4d021a73154202dc50cfaf2adc5567..1c5043a618fff32ebae9e80ee62a3f1b417a3138 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -376,7 +376,7 @@ Module *Module::findOrInferSubmodule(StringRef Name) { Module *Module::getGlobalModuleFragment() const { assert(isNamedModuleUnit() && "We should only query the global module " - "fragment from the C++ 20 Named modules"); + "fragment from the C++20 Named modules"); for (auto *SubModule : SubModules) if (SubModule->isExplicitGlobalModule()) @@ -387,7 +387,7 @@ Module *Module::getGlobalModuleFragment() const { Module *Module::getPrivateModuleFragment() const { assert(isNamedModuleUnit() && "We should only query the private module " - "fragment from the C++ 20 Named modules"); + "fragment from the C++20 Named modules"); for (auto *SubModule : SubModules) if (SubModule->isPrivateModule()) diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 68032961451d90e1b133aa48a7a87bfff6b67d86..dd0218e6ebed81d7e8fd49f62f4f87fb38aa0e9c 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -367,8 +367,20 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, // ACLE predefines. Many can only have one possible value on v8 AArch64. Builder.defineMacro("__ARM_ACLE", "200"); - Builder.defineMacro("__ARM_ARCH", - std::to_string(ArchInfo->Version.getMajor())); + + // __ARM_ARCH is defined as an integer value indicating the current ARM ISA. + // For ISAs up to and including v8, __ARM_ARCH is equal to the major version + // number. For ISAs from v8.1 onwards, __ARM_ARCH is scaled up to include the + // minor version number, e.g. for ARM architecture ARMvX.Y: + // __ARM_ARCH = X * 100 + Y. + if (ArchInfo->Version.getMajor() == 8 && ArchInfo->Version.getMinor() == 0) + Builder.defineMacro("__ARM_ARCH", + std::to_string(ArchInfo->Version.getMajor())); + else + Builder.defineMacro("__ARM_ARCH", + std::to_string(ArchInfo->Version.getMajor() * 100 + + ArchInfo->Version.getMinor().value())); + Builder.defineMacro("__ARM_ARCH_PROFILE", std::string("'") + (char)ArchInfo->Profile + "'"); diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp b/clang/lib/Basic/Targets/AMDGPU.cpp index 141501e8a4d9a146cea0772e4d0f2c6c9588c07e..10cba6b7eac5ccd64bdff9ed7e9b612e11beba6f 100644 --- a/clang/lib/Basic/Targets/AMDGPU.cpp +++ b/clang/lib/Basic/Targets/AMDGPU.cpp @@ -17,6 +17,7 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/MacroBuilder.h" #include "clang/Basic/TargetBuiltins.h" +#include "llvm/ADT/SmallString.h" using namespace clang; using namespace clang::targets; @@ -279,13 +280,25 @@ void AMDGPUTargetInfo::getTargetDefines(const LangOptions &Opts, if (GPUKind == llvm::AMDGPU::GK_NONE && !IsHIPHost) return; - StringRef CanonName = isAMDGCN(getTriple()) ? getArchNameAMDGCN(GPUKind) - : getArchNameR600(GPUKind); + llvm::SmallString<16> CanonName = + (isAMDGCN(getTriple()) ? getArchNameAMDGCN(GPUKind) + : getArchNameR600(GPUKind)); + + // Sanitize the name of generic targets. + // e.g. gfx10.1-generic -> gfx10_1_generic + if (GPUKind >= llvm::AMDGPU::GK_AMDGCN_GENERIC_FIRST && + GPUKind <= llvm::AMDGPU::GK_AMDGCN_GENERIC_LAST) { + std::replace(CanonName.begin(), CanonName.end(), '.', '_'); + std::replace(CanonName.begin(), CanonName.end(), '-', '_'); + } + Builder.defineMacro(Twine("__") + Twine(CanonName) + Twine("__")); // Emit macros for gfx family e.g. gfx906 -> __GFX9__, gfx1030 -> __GFX10___ if (isAMDGCN(getTriple()) && !IsHIPHost) { - assert(CanonName.starts_with("gfx") && "Invalid amdgcn canonical name"); - Builder.defineMacro(Twine("__") + Twine(CanonName.drop_back(2).upper()) + + assert(StringRef(CanonName).starts_with("gfx") && + "Invalid amdgcn canonical name"); + StringRef CanonFamilyName = getArchFamilyNameAMDGCN(GPUKind); + Builder.defineMacro(Twine("__") + Twine(CanonFamilyName.upper()) + Twine("__")); Builder.defineMacro("__amdgcn_processor__", Twine("\"") + Twine(CanonName) + Twine("\"")); diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp index 55b71557452fa04db6b60512368d8ab17c45cac0..cd7fb95259d9db754efe7fdf3a47749656a124fc 100644 --- a/clang/lib/Basic/Targets/ARM.cpp +++ b/clang/lib/Basic/Targets/ARM.cpp @@ -130,6 +130,7 @@ void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) { SubArch = llvm::ARM::getSubArch(ArchKind); ArchProfile = llvm::ARM::parseArchProfile(SubArch); ArchVersion = llvm::ARM::parseArchVersion(SubArch); + ArchMinorVersion = llvm::ARM::parseArchMinorVersion(SubArch); // cache CPU related strings CPUAttr = getCPUAttr(); @@ -736,9 +737,16 @@ void ARMTargetInfo::getTargetDefines(const LangOptions &Opts, if (!CPUAttr.empty()) Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__"); - // ACLE 6.4.1 ARM/Thumb instruction set architecture - // __ARM_ARCH is defined as an integer value indicating the current ARM ISA - Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion)); + // __ARM_ARCH is defined as an integer value indicating the current ARM ISA. + // For ISAs up to and including v8, __ARM_ARCH is equal to the major version + // number. For ISAs from v8.1 onwards, __ARM_ARCH is scaled up to include the + // minor version number, e.g. for ARM architecture ARMvX.Y: + // __ARM_ARCH = X * 100 + Y. + if (ArchVersion >= 9 || ArchMinorVersion != 0) + Builder.defineMacro("__ARM_ARCH", + Twine(ArchVersion * 100 + ArchMinorVersion)); + else + Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion)); if (ArchVersion >= 8) { // ACLE 6.5.7 Crypto Extension diff --git a/clang/lib/Basic/Targets/ARM.h b/clang/lib/Basic/Targets/ARM.h index 9802eb01abf3c43229917479b6ab6c2148ca1649..df06e4d120637a4ec31f043d9b88bc976e527a0b 100644 --- a/clang/lib/Basic/Targets/ARM.h +++ b/clang/lib/Basic/Targets/ARM.h @@ -60,27 +60,45 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo { llvm::ARM::ArchKind ArchKind = llvm::ARM::ArchKind::ARMV4T; llvm::ARM::ProfileKind ArchProfile; unsigned ArchVersion; + unsigned ArchMinorVersion; + LLVM_PREFERRED_TYPE(FPUMode) unsigned FPU : 5; + LLVM_PREFERRED_TYPE(MVEMode) unsigned MVE : 2; + LLVM_PREFERRED_TYPE(bool) unsigned IsAAPCS : 1; + LLVM_PREFERRED_TYPE(HWDivMode) unsigned HWDiv : 2; // Initialized via features. + LLVM_PREFERRED_TYPE(bool) unsigned SoftFloat : 1; + LLVM_PREFERRED_TYPE(bool) unsigned SoftFloatABI : 1; + LLVM_PREFERRED_TYPE(bool) unsigned CRC : 1; + LLVM_PREFERRED_TYPE(bool) unsigned Crypto : 1; + LLVM_PREFERRED_TYPE(bool) unsigned SHA2 : 1; + LLVM_PREFERRED_TYPE(bool) unsigned AES : 1; + LLVM_PREFERRED_TYPE(bool) unsigned DSP : 1; + LLVM_PREFERRED_TYPE(bool) unsigned Unaligned : 1; + LLVM_PREFERRED_TYPE(bool) unsigned DotProd : 1; + LLVM_PREFERRED_TYPE(bool) unsigned HasMatMul : 1; + LLVM_PREFERRED_TYPE(bool) unsigned FPRegsDisabled : 1; + LLVM_PREFERRED_TYPE(bool) unsigned HasPAC : 1; + LLVM_PREFERRED_TYPE(bool) unsigned HasBTI : 1; enum { diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 837a6e799e3a98b2894ab1557e7daa999d2b5071..a6d4af2b88111a4821b7292d3eacb3c1eafab6b5 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -234,7 +234,7 @@ static constexpr Builtin::Info BuiltinInfo[] = { {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, -#include "clang/Basic/BuiltinsRISCV.def" +#include "clang/Basic/BuiltinsRISCV.inc" }; ArrayRef RISCVTargetInfo::getTargetBuiltins() const { diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index e6235f394a6a2ddd9e9136a660ec4e805ec1be7a..e25991e3dfe82133fa5a443fb859d7f845713aa1 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -310,6 +310,7 @@ public: assert(Triple.getEnvironment() >= llvm::Triple::Pixel && Triple.getEnvironment() <= llvm::Triple::Amplification && "Logical SPIR-V environment must be a valid shader stage."); + PointerWidth = PointerAlign = 64; // SPIR-V IDs are represented with a single 32-bit word. SizeType = TargetInfo::UnsignedInt; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index e2511aa1b5c996271398adf4501cef4830a142e4..a310825240237ce51568e01743f72cb52b68f9dd 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -748,7 +748,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline( CodeGenOpts.InstrProfileOutput.empty() ? getDefaultProfileGenName() : CodeGenOpts.InstrProfileOutput, "", "", CodeGenOpts.MemoryProfileUsePath, nullptr, PGOOptions::IRInstr, - PGOOptions::NoCSAction, CodeGenOpts.DebugInfoForProfiling, + PGOOptions::NoCSAction, PGOOptions::ColdFuncOpt::Default, + CodeGenOpts.DebugInfoForProfiling, /*PseudoProbeForProfiling=*/false, CodeGenOpts.AtomicProfileUpdate); else if (CodeGenOpts.hasProfileIRUse()) { // -fprofile-use. @@ -757,28 +758,32 @@ void EmitAssemblyHelper::RunOptimizationPipeline( PGOOpt = PGOOptions( CodeGenOpts.ProfileInstrumentUsePath, "", CodeGenOpts.ProfileRemappingFile, CodeGenOpts.MemoryProfileUsePath, VFS, - PGOOptions::IRUse, CSAction, CodeGenOpts.DebugInfoForProfiling); + PGOOptions::IRUse, CSAction, PGOOptions::ColdFuncOpt::Default, + CodeGenOpts.DebugInfoForProfiling); } else if (!CodeGenOpts.SampleProfileFile.empty()) // -fprofile-sample-use PGOOpt = PGOOptions( CodeGenOpts.SampleProfileFile, "", CodeGenOpts.ProfileRemappingFile, CodeGenOpts.MemoryProfileUsePath, VFS, PGOOptions::SampleUse, - PGOOptions::NoCSAction, CodeGenOpts.DebugInfoForProfiling, - CodeGenOpts.PseudoProbeForProfiling); + PGOOptions::NoCSAction, PGOOptions::ColdFuncOpt::Default, + CodeGenOpts.DebugInfoForProfiling, CodeGenOpts.PseudoProbeForProfiling); else if (!CodeGenOpts.MemoryProfileUsePath.empty()) // -fmemory-profile-use (without any of the above options) PGOOpt = PGOOptions("", "", "", CodeGenOpts.MemoryProfileUsePath, VFS, PGOOptions::NoAction, PGOOptions::NoCSAction, + PGOOptions::ColdFuncOpt::Default, CodeGenOpts.DebugInfoForProfiling); else if (CodeGenOpts.PseudoProbeForProfiling) // -fpseudo-probe-for-profiling PGOOpt = PGOOptions("", "", "", /*MemoryProfile=*/"", nullptr, PGOOptions::NoAction, PGOOptions::NoCSAction, + PGOOptions::ColdFuncOpt::Default, CodeGenOpts.DebugInfoForProfiling, true); else if (CodeGenOpts.DebugInfoForProfiling) // -fdebug-info-for-profiling PGOOpt = PGOOptions("", "", "", /*MemoryProfile=*/"", nullptr, - PGOOptions::NoAction, PGOOptions::NoCSAction, true); + PGOOptions::NoAction, PGOOptions::NoCSAction, + PGOOptions::ColdFuncOpt::Default, true); // Check to see if we want to generate a CS profile. if (CodeGenOpts.hasProfileCSIRInstr()) { @@ -801,7 +806,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline( ? getDefaultProfileGenName() : CodeGenOpts.InstrProfileOutput, "", /*MemoryProfile=*/"", nullptr, PGOOptions::NoAction, - PGOOptions::CSIRInstr, CodeGenOpts.DebugInfoForProfiling); + PGOOptions::CSIRInstr, PGOOptions::ColdFuncOpt::Default, + CodeGenOpts.DebugInfoForProfiling); } if (TM) TM->setPGOOption(PGOOpt); diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index 52e6ddb7d6afb05c217ade3f6c49016550a5e0dd..a8d846b4f6a592b05cb5551fad6e36aa473273ba 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -811,29 +811,6 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *Expr, Address Dest, Builder.SetInsertPoint(ContBB); } -static void -AddDirectArgument(CodeGenFunction &CGF, CallArgList &Args, - bool UseOptimizedLibcall, llvm::Value *Val, QualType ValTy, - SourceLocation Loc, CharUnits SizeInChars) { - if (UseOptimizedLibcall) { - // Load value and pass it to the function directly. - CharUnits Align = CGF.getContext().getTypeAlignInChars(ValTy); - int64_t SizeInBits = CGF.getContext().toBits(SizeInChars); - ValTy = - CGF.getContext().getIntTypeForBitwidth(SizeInBits, /*Signed=*/false); - llvm::Type *ITy = llvm::IntegerType::get(CGF.getLLVMContext(), SizeInBits); - Address Ptr = Address(Val, ITy, Align); - Val = CGF.EmitLoadOfScalar(Ptr, false, - CGF.getContext().getPointerType(ValTy), - Loc); - // Coerce the value into an appropriately sized integer type. - Args.add(RValue::get(Val), ValTy); - } else { - // Non-optimized functions always take a reference. - Args.add(RValue::get(Val), CGF.getContext().VoidPtrTy); - } -} - RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { QualType AtomicTy = E->getPtr()->getType()->getPointeeType(); QualType MemTy = AtomicTy; @@ -857,22 +834,16 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { uint64_t Size = TInfo.Width.getQuantity(); unsigned MaxInlineWidthInBits = getTarget().getMaxAtomicInlineWidth(); - bool Oversized = getContext().toBits(TInfo.Width) > MaxInlineWidthInBits; - bool Misaligned = (Ptr.getAlignment() % TInfo.Width) != 0; - bool UseLibcall = Misaligned | Oversized; - bool ShouldCastToIntPtrTy = true; - CharUnits MaxInlineWidth = getContext().toCharUnitsFromBits(MaxInlineWidthInBits); - DiagnosticsEngine &Diags = CGM.getDiags(); - + bool Misaligned = (Ptr.getAlignment() % TInfo.Width) != 0; + bool Oversized = getContext().toBits(TInfo.Width) > MaxInlineWidthInBits; if (Misaligned) { Diags.Report(E->getBeginLoc(), diag::warn_atomic_op_misaligned) << (int)TInfo.Width.getQuantity() << (int)Ptr.getAlignment().getQuantity(); } - if (Oversized) { Diags.Report(E->getBeginLoc(), diag::warn_atomic_op_oversized) << (int)TInfo.Width.getQuantity() << (int)MaxInlineWidth.getQuantity(); @@ -881,6 +852,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { llvm::Value *Order = EmitScalarExpr(E->getOrder()); llvm::Value *Scope = E->getScopeModel() ? EmitScalarExpr(E->getScope()) : nullptr; + bool ShouldCastToIntPtrTy = true; switch (E->getOp()) { case AtomicExpr::AO__c11_atomic_init: @@ -1047,122 +1019,25 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { Dest = Atomics.castToAtomicIntPointer(Dest); } - // Use a library call. See: http://gcc.gnu.org/wiki/Atomic/GCCMM/LIbrary . + bool PowerOf2Size = (Size & (Size - 1)) == 0; + bool UseLibcall = !PowerOf2Size || (Size > 16); + + // For atomics larger than 16 bytes, emit a libcall from the frontend. This + // avoids the overhead of dealing with excessively-large value types in IR. + // Non-power-of-2 values also lower to libcall here, as they are not currently + // permitted in IR instructions (although that constraint could be relaxed in + // the future). For other cases where a libcall is required on a given + // platform, we let the backend handle it (this includes handling for all of + // the size-optimized libcall variants, which are only valid up to 16 bytes.) + // + // See: https://llvm.org/docs/Atomics.html#libcalls-atomic if (UseLibcall) { - bool UseOptimizedLibcall = false; - switch (E->getOp()) { - case AtomicExpr::AO__c11_atomic_init: - case AtomicExpr::AO__opencl_atomic_init: - llvm_unreachable("Already handled above with EmitAtomicInit!"); - - case AtomicExpr::AO__atomic_fetch_add: - case AtomicExpr::AO__atomic_fetch_and: - case AtomicExpr::AO__atomic_fetch_max: - case AtomicExpr::AO__atomic_fetch_min: - case AtomicExpr::AO__atomic_fetch_nand: - case AtomicExpr::AO__atomic_fetch_or: - case AtomicExpr::AO__atomic_fetch_sub: - case AtomicExpr::AO__atomic_fetch_xor: - case AtomicExpr::AO__atomic_add_fetch: - case AtomicExpr::AO__atomic_and_fetch: - case AtomicExpr::AO__atomic_max_fetch: - case AtomicExpr::AO__atomic_min_fetch: - case AtomicExpr::AO__atomic_nand_fetch: - case AtomicExpr::AO__atomic_or_fetch: - case AtomicExpr::AO__atomic_sub_fetch: - case AtomicExpr::AO__atomic_xor_fetch: - case AtomicExpr::AO__c11_atomic_fetch_add: - case AtomicExpr::AO__c11_atomic_fetch_and: - case AtomicExpr::AO__c11_atomic_fetch_max: - case AtomicExpr::AO__c11_atomic_fetch_min: - case AtomicExpr::AO__c11_atomic_fetch_nand: - case AtomicExpr::AO__c11_atomic_fetch_or: - case AtomicExpr::AO__c11_atomic_fetch_sub: - case AtomicExpr::AO__c11_atomic_fetch_xor: - case AtomicExpr::AO__hip_atomic_fetch_add: - case AtomicExpr::AO__hip_atomic_fetch_and: - case AtomicExpr::AO__hip_atomic_fetch_max: - case AtomicExpr::AO__hip_atomic_fetch_min: - case AtomicExpr::AO__hip_atomic_fetch_or: - case AtomicExpr::AO__hip_atomic_fetch_sub: - case AtomicExpr::AO__hip_atomic_fetch_xor: - case AtomicExpr::AO__opencl_atomic_fetch_add: - case AtomicExpr::AO__opencl_atomic_fetch_and: - case AtomicExpr::AO__opencl_atomic_fetch_max: - case AtomicExpr::AO__opencl_atomic_fetch_min: - case AtomicExpr::AO__opencl_atomic_fetch_or: - case AtomicExpr::AO__opencl_atomic_fetch_sub: - case AtomicExpr::AO__opencl_atomic_fetch_xor: - case AtomicExpr::AO__scoped_atomic_fetch_add: - case AtomicExpr::AO__scoped_atomic_fetch_and: - case AtomicExpr::AO__scoped_atomic_fetch_max: - case AtomicExpr::AO__scoped_atomic_fetch_min: - case AtomicExpr::AO__scoped_atomic_fetch_nand: - case AtomicExpr::AO__scoped_atomic_fetch_or: - case AtomicExpr::AO__scoped_atomic_fetch_sub: - case AtomicExpr::AO__scoped_atomic_fetch_xor: - case AtomicExpr::AO__scoped_atomic_add_fetch: - case AtomicExpr::AO__scoped_atomic_and_fetch: - case AtomicExpr::AO__scoped_atomic_max_fetch: - case AtomicExpr::AO__scoped_atomic_min_fetch: - case AtomicExpr::AO__scoped_atomic_nand_fetch: - case AtomicExpr::AO__scoped_atomic_or_fetch: - case AtomicExpr::AO__scoped_atomic_sub_fetch: - case AtomicExpr::AO__scoped_atomic_xor_fetch: - // For these, only library calls for certain sizes exist. - UseOptimizedLibcall = true; - break; - - case AtomicExpr::AO__atomic_load: - case AtomicExpr::AO__atomic_store: - case AtomicExpr::AO__atomic_exchange: - case AtomicExpr::AO__atomic_compare_exchange: - case AtomicExpr::AO__scoped_atomic_load: - case AtomicExpr::AO__scoped_atomic_store: - case AtomicExpr::AO__scoped_atomic_exchange: - case AtomicExpr::AO__scoped_atomic_compare_exchange: - // Use the generic version if we don't know that the operand will be - // suitably aligned for the optimized version. - if (Misaligned) - break; - [[fallthrough]]; - case AtomicExpr::AO__atomic_load_n: - case AtomicExpr::AO__atomic_store_n: - case AtomicExpr::AO__atomic_exchange_n: - case AtomicExpr::AO__atomic_compare_exchange_n: - case AtomicExpr::AO__c11_atomic_load: - case AtomicExpr::AO__c11_atomic_store: - case AtomicExpr::AO__c11_atomic_exchange: - case AtomicExpr::AO__c11_atomic_compare_exchange_weak: - case AtomicExpr::AO__c11_atomic_compare_exchange_strong: - case AtomicExpr::AO__hip_atomic_load: - case AtomicExpr::AO__hip_atomic_store: - case AtomicExpr::AO__hip_atomic_exchange: - case AtomicExpr::AO__hip_atomic_compare_exchange_weak: - case AtomicExpr::AO__hip_atomic_compare_exchange_strong: - case AtomicExpr::AO__opencl_atomic_load: - case AtomicExpr::AO__opencl_atomic_store: - case AtomicExpr::AO__opencl_atomic_exchange: - case AtomicExpr::AO__opencl_atomic_compare_exchange_weak: - case AtomicExpr::AO__opencl_atomic_compare_exchange_strong: - case AtomicExpr::AO__scoped_atomic_load_n: - case AtomicExpr::AO__scoped_atomic_store_n: - case AtomicExpr::AO__scoped_atomic_exchange_n: - case AtomicExpr::AO__scoped_atomic_compare_exchange_n: - // Only use optimized library calls for sizes for which they exist. - // FIXME: Size == 16 optimized library functions exist too. - if (Size == 1 || Size == 2 || Size == 4 || Size == 8) - UseOptimizedLibcall = true; - break; - } - CallArgList Args; - if (!UseOptimizedLibcall) { - // For non-optimized library calls, the size is the first parameter - Args.add(RValue::get(llvm::ConstantInt::get(SizeTy, Size)), - getContext().getSizeType()); - } - // Atomic address is the first or second parameter + // For non-optimized library calls, the size is the first parameter. + Args.add(RValue::get(llvm::ConstantInt::get(SizeTy, Size)), + getContext().getSizeType()); + + // The atomic address is the second parameter. // The OpenCL atomic library functions only accept pointer arguments to // generic address space. auto CastToGenericAddrSpace = [&](llvm::Value *V, QualType PT) { @@ -1177,18 +1052,14 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { return getTargetHooks().performAddrSpaceCast( *this, V, AS, LangAS::opencl_generic, DestType, false); }; - Args.add(RValue::get(CastToGenericAddrSpace(Ptr.getPointer(), E->getPtr()->getType())), getContext().VoidPtrTy); + // The next 1-3 parameters are op-dependent. std::string LibCallName; - QualType LoweredMemTy = - MemTy->isPointerType() ? getContext().getIntPtrType() : MemTy; QualType RetTy; bool HaveRetTy = false; - llvm::Instruction::BinaryOps PostOp = (llvm::Instruction::BinaryOps)0; - bool PostOpMinMax = false; switch (E->getOp()) { case AtomicExpr::AO__c11_atomic_init: case AtomicExpr::AO__opencl_atomic_init: @@ -1199,8 +1070,6 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { // and exchange. // bool __atomic_compare_exchange(size_t size, void *mem, void *expected, // void *desired, int success, int failure) - // bool __atomic_compare_exchange_N(T *mem, T *expected, T desired, - // int success, int failure) case AtomicExpr::AO__atomic_compare_exchange: case AtomicExpr::AO__atomic_compare_exchange_n: case AtomicExpr::AO__c11_atomic_compare_exchange_weak: @@ -1217,14 +1086,14 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), E->getVal1()->getType())), getContext().VoidPtrTy); - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val2.getPointer(), - MemTy, E->getExprLoc(), TInfo.Width); + Args.add(RValue::get(CastToGenericAddrSpace(Val2.getPointer(), + E->getVal2()->getType())), + getContext().VoidPtrTy); Args.add(RValue::get(Order), getContext().IntTy); Order = OrderFail; break; // void __atomic_exchange(size_t size, void *mem, void *val, void *return, // int order) - // T __atomic_exchange_N(T *mem, T val, int order) case AtomicExpr::AO__atomic_exchange: case AtomicExpr::AO__atomic_exchange_n: case AtomicExpr::AO__c11_atomic_exchange: @@ -1233,11 +1102,11 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__scoped_atomic_exchange: case AtomicExpr::AO__scoped_atomic_exchange_n: LibCallName = "__atomic_exchange"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - MemTy, E->getExprLoc(), TInfo.Width); + Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), + E->getVal1()->getType())), + getContext().VoidPtrTy); break; // void __atomic_store(size_t size, void *mem, void *val, int order) - // void __atomic_store_N(T *mem, T val, int order) case AtomicExpr::AO__atomic_store: case AtomicExpr::AO__atomic_store_n: case AtomicExpr::AO__c11_atomic_store: @@ -1248,11 +1117,11 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { LibCallName = "__atomic_store"; RetTy = getContext().VoidTy; HaveRetTy = true; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - MemTy, E->getExprLoc(), TInfo.Width); + Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), + E->getVal1()->getType())), + getContext().VoidPtrTy); break; // void __atomic_load(size_t size, void *mem, void *return, int order) - // T __atomic_load_N(T *mem, int order) case AtomicExpr::AO__atomic_load: case AtomicExpr::AO__atomic_load_n: case AtomicExpr::AO__c11_atomic_load: @@ -1262,183 +1131,85 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__scoped_atomic_load_n: LibCallName = "__atomic_load"; break; - // T __atomic_add_fetch_N(T *mem, T val, int order) - // T __atomic_fetch_add_N(T *mem, T val, int order) case AtomicExpr::AO__atomic_add_fetch: case AtomicExpr::AO__scoped_atomic_add_fetch: - PostOp = llvm::Instruction::Add; - [[fallthrough]]; case AtomicExpr::AO__atomic_fetch_add: case AtomicExpr::AO__c11_atomic_fetch_add: case AtomicExpr::AO__hip_atomic_fetch_add: case AtomicExpr::AO__opencl_atomic_fetch_add: case AtomicExpr::AO__scoped_atomic_fetch_add: - LibCallName = "__atomic_fetch_add"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - LoweredMemTy, E->getExprLoc(), TInfo.Width); - break; - // T __atomic_and_fetch_N(T *mem, T val, int order) - // T __atomic_fetch_and_N(T *mem, T val, int order) case AtomicExpr::AO__atomic_and_fetch: case AtomicExpr::AO__scoped_atomic_and_fetch: - PostOp = llvm::Instruction::And; - [[fallthrough]]; case AtomicExpr::AO__atomic_fetch_and: case AtomicExpr::AO__c11_atomic_fetch_and: case AtomicExpr::AO__hip_atomic_fetch_and: case AtomicExpr::AO__opencl_atomic_fetch_and: case AtomicExpr::AO__scoped_atomic_fetch_and: - LibCallName = "__atomic_fetch_and"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - MemTy, E->getExprLoc(), TInfo.Width); - break; - // T __atomic_or_fetch_N(T *mem, T val, int order) - // T __atomic_fetch_or_N(T *mem, T val, int order) case AtomicExpr::AO__atomic_or_fetch: case AtomicExpr::AO__scoped_atomic_or_fetch: - PostOp = llvm::Instruction::Or; - [[fallthrough]]; case AtomicExpr::AO__atomic_fetch_or: case AtomicExpr::AO__c11_atomic_fetch_or: case AtomicExpr::AO__hip_atomic_fetch_or: case AtomicExpr::AO__opencl_atomic_fetch_or: case AtomicExpr::AO__scoped_atomic_fetch_or: - LibCallName = "__atomic_fetch_or"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - MemTy, E->getExprLoc(), TInfo.Width); - break; - // T __atomic_sub_fetch_N(T *mem, T val, int order) - // T __atomic_fetch_sub_N(T *mem, T val, int order) case AtomicExpr::AO__atomic_sub_fetch: case AtomicExpr::AO__scoped_atomic_sub_fetch: - PostOp = llvm::Instruction::Sub; - [[fallthrough]]; case AtomicExpr::AO__atomic_fetch_sub: case AtomicExpr::AO__c11_atomic_fetch_sub: case AtomicExpr::AO__hip_atomic_fetch_sub: case AtomicExpr::AO__opencl_atomic_fetch_sub: case AtomicExpr::AO__scoped_atomic_fetch_sub: - LibCallName = "__atomic_fetch_sub"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - LoweredMemTy, E->getExprLoc(), TInfo.Width); - break; - // T __atomic_xor_fetch_N(T *mem, T val, int order) - // T __atomic_fetch_xor_N(T *mem, T val, int order) case AtomicExpr::AO__atomic_xor_fetch: case AtomicExpr::AO__scoped_atomic_xor_fetch: - PostOp = llvm::Instruction::Xor; - [[fallthrough]]; case AtomicExpr::AO__atomic_fetch_xor: case AtomicExpr::AO__c11_atomic_fetch_xor: case AtomicExpr::AO__hip_atomic_fetch_xor: case AtomicExpr::AO__opencl_atomic_fetch_xor: case AtomicExpr::AO__scoped_atomic_fetch_xor: - LibCallName = "__atomic_fetch_xor"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - MemTy, E->getExprLoc(), TInfo.Width); - break; + case AtomicExpr::AO__atomic_nand_fetch: + case AtomicExpr::AO__atomic_fetch_nand: + case AtomicExpr::AO__c11_atomic_fetch_nand: + case AtomicExpr::AO__scoped_atomic_fetch_nand: + case AtomicExpr::AO__scoped_atomic_nand_fetch: case AtomicExpr::AO__atomic_min_fetch: - case AtomicExpr::AO__scoped_atomic_min_fetch: - PostOpMinMax = true; - [[fallthrough]]; case AtomicExpr::AO__atomic_fetch_min: case AtomicExpr::AO__c11_atomic_fetch_min: - case AtomicExpr::AO__scoped_atomic_fetch_min: case AtomicExpr::AO__hip_atomic_fetch_min: case AtomicExpr::AO__opencl_atomic_fetch_min: - LibCallName = E->getValueType()->isSignedIntegerType() - ? "__atomic_fetch_min" - : "__atomic_fetch_umin"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - LoweredMemTy, E->getExprLoc(), TInfo.Width); - break; + case AtomicExpr::AO__scoped_atomic_fetch_min: + case AtomicExpr::AO__scoped_atomic_min_fetch: case AtomicExpr::AO__atomic_max_fetch: - case AtomicExpr::AO__scoped_atomic_max_fetch: - PostOpMinMax = true; - [[fallthrough]]; case AtomicExpr::AO__atomic_fetch_max: case AtomicExpr::AO__c11_atomic_fetch_max: case AtomicExpr::AO__hip_atomic_fetch_max: case AtomicExpr::AO__opencl_atomic_fetch_max: case AtomicExpr::AO__scoped_atomic_fetch_max: - LibCallName = E->getValueType()->isSignedIntegerType() - ? "__atomic_fetch_max" - : "__atomic_fetch_umax"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - LoweredMemTy, E->getExprLoc(), TInfo.Width); - break; - // T __atomic_nand_fetch_N(T *mem, T val, int order) - // T __atomic_fetch_nand_N(T *mem, T val, int order) - case AtomicExpr::AO__atomic_nand_fetch: - case AtomicExpr::AO__scoped_atomic_nand_fetch: - PostOp = llvm::Instruction::And; // the NOT is special cased below - [[fallthrough]]; - case AtomicExpr::AO__atomic_fetch_nand: - case AtomicExpr::AO__c11_atomic_fetch_nand: - case AtomicExpr::AO__scoped_atomic_fetch_nand: - LibCallName = "__atomic_fetch_nand"; - AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), - MemTy, E->getExprLoc(), TInfo.Width); - break; + case AtomicExpr::AO__scoped_atomic_max_fetch: + llvm_unreachable("Integral atomic operations always become atomicrmw!"); } if (E->isOpenCL()) { - LibCallName = std::string("__opencl") + - StringRef(LibCallName).drop_front(1).str(); - + LibCallName = + std::string("__opencl") + StringRef(LibCallName).drop_front(1).str(); } - // Optimized functions have the size in their name. - if (UseOptimizedLibcall) - LibCallName += "_" + llvm::utostr(Size); // By default, assume we return a value of the atomic type. if (!HaveRetTy) { - if (UseOptimizedLibcall) { - // Value is returned directly. - // The function returns an appropriately sized integer type. - RetTy = getContext().getIntTypeForBitwidth( - getContext().toBits(TInfo.Width), /*Signed=*/false); - } else { - // Value is returned through parameter before the order. - RetTy = getContext().VoidTy; - Args.add(RValue::get(Dest.getPointer()), getContext().VoidPtrTy); - } + // Value is returned through parameter before the order. + RetTy = getContext().VoidTy; + Args.add(RValue::get(CastToGenericAddrSpace(Dest.getPointer(), RetTy)), + getContext().VoidPtrTy); } - // order is always the last parameter + // Order is always the last parameter. Args.add(RValue::get(Order), getContext().IntTy); if (E->isOpenCL()) Args.add(RValue::get(Scope), getContext().IntTy); - // PostOp is only needed for the atomic_*_fetch operations, and - // thus is only needed for and implemented in the - // UseOptimizedLibcall codepath. - assert(UseOptimizedLibcall || (!PostOp && !PostOpMinMax)); - RValue Res = emitAtomicLibcall(*this, LibCallName, RetTy, Args); // The value is returned directly from the libcall. if (E->isCmpXChg()) return Res; - // The value is returned directly for optimized libcalls but the expr - // provided an out-param. - if (UseOptimizedLibcall && Res.getScalarVal()) { - llvm::Value *ResVal = Res.getScalarVal(); - if (PostOpMinMax) { - llvm::Value *LoadVal1 = Args[1].getRValue(*this).getScalarVal(); - ResVal = EmitPostAtomicMinMax(Builder, E->getOp(), - E->getValueType()->isSignedIntegerType(), - ResVal, LoadVal1); - } else if (PostOp) { - llvm::Value *LoadVal1 = Args[1].getRValue(*this).getScalarVal(); - ResVal = Builder.CreateBinOp(PostOp, ResVal, LoadVal1); - } - if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch || - E->getOp() == AtomicExpr::AO__scoped_atomic_nand_fetch) - ResVal = Builder.CreateNot(ResVal); - - Builder.CreateStore(ResVal, Dest.withElementType(ResVal->getType())); - } - if (RValTy->isVoidType()) return RValue::get(nullptr); diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index e051cbc64863536248725dd9432e4459abd7ef1b..ee0b75047696223feb1e80a824140aca47736278 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3443,6 +3443,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Function *F = CGM.getIntrinsic(Intrinsic::readcyclecounter); return RValue::get(Builder.CreateCall(F)); } + case Builtin::BI__builtin_readsteadycounter: { + Function *F = CGM.getIntrinsic(Intrinsic::readsteadycounter); + return RValue::get(Builder.CreateCall(F)); + } case Builtin::BI__builtin___clear_cache: { Value *Begin = EmitScalarExpr(E->getArg(0)); Value *End = EmitScalarExpr(E->getArg(1)); @@ -5908,7 +5912,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, } } - assert(PTy->canLosslesslyBitCastTo(FTy->getParamType(i)) && + assert(ArgValue->getType()->canLosslesslyBitCastTo(PTy) && "Must be able to losslessly bit cast to param"); // Cast vector type (e.g., v256i32) to x86_amx, this only happen // in amx intrinsics. diff --git a/clang/lib/CodeGen/CGCUDARuntime.h b/clang/lib/CodeGen/CGCUDARuntime.h index c7af8f1cf0fe95ee7d1e7ded0cec6507198f6967..8030d632cc3d28cf461325ea12dd56f095816265 100644 --- a/clang/lib/CodeGen/CGCUDARuntime.h +++ b/clang/lib/CodeGen/CGCUDARuntime.h @@ -54,10 +54,15 @@ public: }; private: + LLVM_PREFERRED_TYPE(DeviceVarKind) unsigned Kind : 2; + LLVM_PREFERRED_TYPE(bool) unsigned Extern : 1; + LLVM_PREFERRED_TYPE(bool) unsigned Constant : 1; // Constant variable. + LLVM_PREFERRED_TYPE(bool) unsigned Managed : 1; // Managed variable. + LLVM_PREFERRED_TYPE(bool) unsigned Normalized : 1; // Normalized texture. int SurfTexType; // Type of surface/texutre. diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index cd26a3df78602ce6fcad6c2d75bc8fde296df472..d05cf1c6e1814ebe01d73ff8291803fa3374973f 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1301,27 +1301,25 @@ static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty, // If coercing a fixed vector to a scalable vector for ABI compatibility, and // the types match, use the llvm.vector.insert intrinsic to perform the // conversion. - if (auto *ScalableDst = dyn_cast(Ty)) { - if (auto *FixedSrc = dyn_cast(SrcTy)) { - // If we are casting a fixed i8 vector to a scalable 16 x i1 predicate + if (auto *ScalableDstTy = dyn_cast(Ty)) { + if (auto *FixedSrcTy = dyn_cast(SrcTy)) { + // If we are casting a fixed i8 vector to a scalable i1 predicate // vector, use a vector insert and bitcast the result. - bool NeedsBitcast = false; - auto PredType = - llvm::ScalableVectorType::get(CGF.Builder.getInt1Ty(), 16); - llvm::Type *OrigType = Ty; - if (ScalableDst == PredType && - FixedSrc->getElementType() == CGF.Builder.getInt8Ty()) { - ScalableDst = llvm::ScalableVectorType::get(CGF.Builder.getInt8Ty(), 2); - NeedsBitcast = true; + if (ScalableDstTy->getElementType()->isIntegerTy(1) && + ScalableDstTy->getElementCount().isKnownMultipleOf(8) && + FixedSrcTy->getElementType()->isIntegerTy(8)) { + ScalableDstTy = llvm::ScalableVectorType::get( + FixedSrcTy->getElementType(), + ScalableDstTy->getElementCount().getKnownMinValue() / 8); } - if (ScalableDst->getElementType() == FixedSrc->getElementType()) { + if (ScalableDstTy->getElementType() == FixedSrcTy->getElementType()) { auto *Load = CGF.Builder.CreateLoad(Src); - auto *UndefVec = llvm::UndefValue::get(ScalableDst); + auto *UndefVec = llvm::UndefValue::get(ScalableDstTy); auto *Zero = llvm::Constant::getNullValue(CGF.CGM.Int64Ty); llvm::Value *Result = CGF.Builder.CreateInsertVector( - ScalableDst, UndefVec, Load, Zero, "cast.scalable"); - if (NeedsBitcast) - Result = CGF.Builder.CreateBitCast(Result, OrigType); + ScalableDstTy, UndefVec, Load, Zero, "cast.scalable"); + if (ScalableDstTy != Ty) + Result = CGF.Builder.CreateBitCast(Result, Ty); return Result; } } @@ -3199,13 +3197,14 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, llvm::Value *Coerced = Fn->getArg(FirstIRArg); if (auto *VecTyFrom = dyn_cast(Coerced->getType())) { - // If we are casting a scalable 16 x i1 predicate vector to a fixed i8 + // If we are casting a scalable i1 predicate vector to a fixed i8 // vector, bitcast the source and use a vector extract. - auto PredType = - llvm::ScalableVectorType::get(Builder.getInt1Ty(), 16); - if (VecTyFrom == PredType && + if (VecTyFrom->getElementType()->isIntegerTy(1) && + VecTyFrom->getElementCount().isKnownMultipleOf(8) && VecTyTo->getElementType() == Builder.getInt8Ty()) { - VecTyFrom = llvm::ScalableVectorType::get(Builder.getInt8Ty(), 2); + VecTyFrom = llvm::ScalableVectorType::get( + VecTyTo->getElementType(), + VecTyFrom->getElementCount().getKnownMinValue() / 8); Coerced = Builder.CreateBitCast(Coerced, VecTyFrom); } if (VecTyFrom->getElementType() == VecTyTo->getElementType()) { @@ -5877,12 +5876,13 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // If coercing a fixed vector from a scalable vector for ABI // compatibility, and the types match, use the llvm.vector.extract // intrinsic to perform the conversion. - if (auto *FixedDst = dyn_cast(RetIRTy)) { + if (auto *FixedDstTy = dyn_cast(RetIRTy)) { llvm::Value *V = CI; - if (auto *ScalableSrc = dyn_cast(V->getType())) { - if (FixedDst->getElementType() == ScalableSrc->getElementType()) { + if (auto *ScalableSrcTy = + dyn_cast(V->getType())) { + if (FixedDstTy->getElementType() == ScalableSrcTy->getElementType()) { llvm::Value *Zero = llvm::Constant::getNullValue(CGM.Int64Ty); - V = Builder.CreateExtractVector(FixedDst, V, Zero, "cast.fixed"); + V = Builder.CreateExtractVector(FixedDstTy, V, Zero, "cast.fixed"); return RValue::get(V); } } diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h index 1c0d15dc932ad80f8ca6a684bcbf3380857c0f59..1bd48a07259307486a53f2eba0de9f221274d219 100644 --- a/clang/lib/CodeGen/CGCall.h +++ b/clang/lib/CodeGen/CGCall.h @@ -357,8 +357,11 @@ class ReturnValueSlot { Address Addr = Address::invalid(); // Return value slot flags + LLVM_PREFERRED_TYPE(bool) unsigned IsVolatile : 1; + LLVM_PREFERRED_TYPE(bool) unsigned IsUnused : 1; + LLVM_PREFERRED_TYPE(bool) unsigned IsExternallyDestructed : 1; public: diff --git a/clang/lib/CodeGen/CGCleanup.h b/clang/lib/CodeGen/CGCleanup.h index fcfbf41b0eaff58cff1c4fda90c340a2977c5d62..7a7344c07160db388ba8d743a37c245069c9af9c 100644 --- a/clang/lib/CodeGen/CGCleanup.h +++ b/clang/lib/CodeGen/CGCleanup.h @@ -40,6 +40,10 @@ struct CatchTypeInfo { /// A protected scope for zero-cost EH handling. class EHScope { +public: + enum Kind { Cleanup, Catch, Terminate, Filter }; + +private: llvm::BasicBlock *CachedLandingPad; llvm::BasicBlock *CachedEHDispatchBlock; @@ -47,6 +51,7 @@ class EHScope { class CommonBitFields { friend class EHScope; + LLVM_PREFERRED_TYPE(Kind) unsigned Kind : 3; }; enum { NumCommonBits = 3 }; @@ -64,21 +69,27 @@ protected: unsigned : NumCommonBits; /// Whether this cleanup needs to be run along normal edges. + LLVM_PREFERRED_TYPE(bool) unsigned IsNormalCleanup : 1; /// Whether this cleanup needs to be run along exception edges. + LLVM_PREFERRED_TYPE(bool) unsigned IsEHCleanup : 1; /// Whether this cleanup is currently active. + LLVM_PREFERRED_TYPE(bool) unsigned IsActive : 1; /// Whether this cleanup is a lifetime marker + LLVM_PREFERRED_TYPE(bool) unsigned IsLifetimeMarker : 1; /// Whether the normal cleanup should test the activation flag. + LLVM_PREFERRED_TYPE(bool) unsigned TestFlagInNormalCleanup : 1; /// Whether the EH cleanup should test the activation flag. + LLVM_PREFERRED_TYPE(bool) unsigned TestFlagInEHCleanup : 1; /// The amount of extra storage needed by the Cleanup. @@ -101,8 +112,6 @@ protected: }; public: - enum Kind { Cleanup, Catch, Terminate, Filter }; - EHScope(Kind kind, EHScopeStack::stable_iterator enclosingEHScope) : CachedLandingPad(nullptr), CachedEHDispatchBlock(nullptr), EnclosingEHScope(enclosingEHScope) { diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index d136bfc37278f0ae7b32be0bfe95234e5e9cb4cd..2adbef6d55122c973a195260ad218354723ff035 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -1423,6 +1423,7 @@ namespace { }; unsigned NumPlacementArgs : 31; + LLVM_PREFERRED_TYPE(bool) unsigned PassAlignmentToPlacementDelete : 1; const FunctionDecl *OperatorDelete; ValueTy Ptr; diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index df8f71cf1d90086ec6509cab8c62fc21cedd8bb8..aa805f291d1757fb0f1bb1694dff6a3841494a21 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2137,26 +2137,24 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { // If Src is a fixed vector and Dst is a scalable vector, and both have the // same element type, use the llvm.vector.insert intrinsic to perform the // bitcast. - if (const auto *FixedSrc = dyn_cast(SrcTy)) { - if (const auto *ScalableDst = dyn_cast(DstTy)) { - // If we are casting a fixed i8 vector to a scalable 16 x i1 predicate + if (auto *FixedSrcTy = dyn_cast(SrcTy)) { + if (auto *ScalableDstTy = dyn_cast(DstTy)) { + // If we are casting a fixed i8 vector to a scalable i1 predicate // vector, use a vector insert and bitcast the result. - bool NeedsBitCast = false; - auto PredType = llvm::ScalableVectorType::get(Builder.getInt1Ty(), 16); - llvm::Type *OrigType = DstTy; - if (ScalableDst == PredType && - FixedSrc->getElementType() == Builder.getInt8Ty()) { - DstTy = llvm::ScalableVectorType::get(Builder.getInt8Ty(), 2); - ScalableDst = cast(DstTy); - NeedsBitCast = true; + if (ScalableDstTy->getElementType()->isIntegerTy(1) && + ScalableDstTy->getElementCount().isKnownMultipleOf(8) && + FixedSrcTy->getElementType()->isIntegerTy(8)) { + ScalableDstTy = llvm::ScalableVectorType::get( + FixedSrcTy->getElementType(), + ScalableDstTy->getElementCount().getKnownMinValue() / 8); } - if (FixedSrc->getElementType() == ScalableDst->getElementType()) { - llvm::Value *UndefVec = llvm::UndefValue::get(DstTy); + if (FixedSrcTy->getElementType() == ScalableDstTy->getElementType()) { + llvm::Value *UndefVec = llvm::UndefValue::get(ScalableDstTy); llvm::Value *Zero = llvm::Constant::getNullValue(CGF.CGM.Int64Ty); llvm::Value *Result = Builder.CreateInsertVector( - DstTy, UndefVec, Src, Zero, "cast.scalable"); - if (NeedsBitCast) - Result = Builder.CreateBitCast(Result, OrigType); + ScalableDstTy, UndefVec, Src, Zero, "cast.scalable"); + if (Result->getType() != DstTy) + Result = Builder.CreateBitCast(Result, DstTy); return Result; } } @@ -2165,18 +2163,19 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { // If Src is a scalable vector and Dst is a fixed vector, and both have the // same element type, use the llvm.vector.extract intrinsic to perform the // bitcast. - if (const auto *ScalableSrc = dyn_cast(SrcTy)) { - if (const auto *FixedDst = dyn_cast(DstTy)) { - // If we are casting a scalable 16 x i1 predicate vector to a fixed i8 + if (auto *ScalableSrcTy = dyn_cast(SrcTy)) { + if (auto *FixedDstTy = dyn_cast(DstTy)) { + // If we are casting a scalable i1 predicate vector to a fixed i8 // vector, bitcast the source and use a vector extract. - auto PredType = llvm::ScalableVectorType::get(Builder.getInt1Ty(), 16); - if (ScalableSrc == PredType && - FixedDst->getElementType() == Builder.getInt8Ty()) { - SrcTy = llvm::ScalableVectorType::get(Builder.getInt8Ty(), 2); - ScalableSrc = cast(SrcTy); - Src = Builder.CreateBitCast(Src, SrcTy); + if (ScalableSrcTy->getElementType()->isIntegerTy(1) && + ScalableSrcTy->getElementCount().isKnownMultipleOf(8) && + FixedDstTy->getElementType()->isIntegerTy(8)) { + ScalableSrcTy = llvm::ScalableVectorType::get( + FixedDstTy->getElementType(), + ScalableSrcTy->getElementCount().getKnownMinValue() / 8); + Src = Builder.CreateBitCast(Src, ScalableSrcTy); } - if (ScalableSrc->getElementType() == FixedDst->getElementType()) { + if (ScalableSrcTy->getElementType() == FixedDstTy->getElementType()) { llvm::Value *Zero = llvm::Constant::getNullValue(CGF.CGM.Int64Ty); return Builder.CreateExtractVector(DstTy, Src, Zero, "cast.fixed"); } @@ -4168,7 +4167,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) { bool SanitizeBase = SanitizeSignedBase || SanitizeUnsignedBase; bool SanitizeExponent = CGF.SanOpts.has(SanitizerKind::ShiftExponent); // OpenCL 6.3j: shift values are effectively % word size of LHS. - if (CGF.getLangOpts().OpenCL) + if (CGF.getLangOpts().OpenCL || CGF.getLangOpts().HLSL) RHS = ConstrainShiftValue(Ops.LHS, RHS, "shl.mask"); else if ((SanitizeBase || SanitizeExponent) && isa(Ops.LHS->getType())) { @@ -4237,7 +4236,7 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) { RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom"); // OpenCL 6.3j: shift values are effectively % word size of LHS. - if (CGF.getLangOpts().OpenCL) + if (CGF.getLangOpts().OpenCL || CGF.getLangOpts().HLSL) RHS = ConstrainShiftValue(Ops.LHS, RHS, "shr.mask"); else if (CGF.SanOpts.has(SanitizerKind::ShiftExponent) && isa(Ops.LHS->getType())) { diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 03fc0ec7ff54e1ccf582c1eeba5e46f841dbaf86..f3a948cf13f9c9098f8497a28aa1ee9102f59939 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -899,9 +899,13 @@ namespace { const ObjCPropertyImplDecl *propImpl); private: + LLVM_PREFERRED_TYPE(StrategyKind) unsigned Kind : 8; + LLVM_PREFERRED_TYPE(bool) unsigned IsAtomic : 1; + LLVM_PREFERRED_TYPE(bool) unsigned IsCopy : 1; + LLVM_PREFERRED_TYPE(bool) unsigned HasStrong : 1; CharUnits IvarSize; diff --git a/clang/lib/CodeGen/CGRecordLayout.h b/clang/lib/CodeGen/CGRecordLayout.h index d5ea74922603b763805f99533bc20600a16cdae5..6c06ad20fbe56b1e69c19a71f2c7344364739163 100644 --- a/clang/lib/CodeGen/CGRecordLayout.h +++ b/clang/lib/CodeGen/CGRecordLayout.h @@ -71,6 +71,7 @@ struct CGBitFieldInfo { unsigned Size : 15; /// Whether the bit-field is signed. + LLVM_PREFERRED_TYPE(bool) unsigned IsSigned : 1; /// The storage size in bits which should be used when accessing this diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index beff0ad9da2709c1fd985516623235bc788a14da..af51875782c9fff2fe6ecb2cb7fa157704886c92 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -435,6 +435,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef Attrs) { case Stmt::OMPParallelMaskedDirectiveClass: EmitOMPParallelMaskedDirective(cast(*S)); break; + case Stmt::OpenACCComputeConstructClass: + EmitOpenACCComputeConstruct(cast(*S)); + break; } } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 143ad64e8816b12ee5297ab6689ca058b6e1aa96..caa6a327550baa224745058e66c4fe57dc260d81 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -26,6 +26,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" +#include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" #include "clang/AST/Type.h" #include "clang/Basic/ABI.h" @@ -203,6 +204,7 @@ template <> struct DominatingValue { llvm::Value *Value; llvm::Type *ElementType; + LLVM_PREFERRED_TYPE(Kind) unsigned K : 3; unsigned Align : 29; saved_type(llvm::Value *v, llvm::Type *e, Kind k, unsigned a = 0) @@ -650,9 +652,11 @@ public: struct LifetimeExtendedCleanupHeader { /// The size of the following cleanup object. unsigned Size; - /// The kind of cleanup to push: a value from the CleanupKind enumeration. + /// The kind of cleanup to push. + LLVM_PREFERRED_TYPE(CleanupKind) unsigned Kind : 31; /// Whether this is a conditional cleanup. + LLVM_PREFERRED_TYPE(bool) unsigned IsConditional : 1; size_t getSize() const { return Size; } @@ -3837,6 +3841,15 @@ private: void EmitSections(const OMPExecutableDirective &S); public: + //===--------------------------------------------------------------------===// + // OpenACC Emission + //===--------------------------------------------------------------------===// + void EmitOpenACCComputeConstruct(const OpenACCComputeConstruct &S) { + // TODO OpenACC: Implement this. It is currently implemented as a 'no-op', + // simply emitting its structured block, but in the future we will implement + // some sort of IR. + EmitStmt(S.getStructuredBlock()); + } //===--------------------------------------------------------------------===// // LValue Expression Emission diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 36b63d78b06f83c2ae0d0def60a14dac2c5008c5..2f923d5457f9cff2f7fa2b442c626f95c6c1b66b 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -30,6 +30,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" @@ -4212,7 +4213,8 @@ void CodeGenModule::emitMultiVersionFunctions() { llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver(GD); if (auto *IFunc = dyn_cast(ResolverConstant)) { ResolverConstant = IFunc->getResolver(); - if (FD->isTargetClonesMultiVersion()) { + if (FD->isTargetClonesMultiVersion() || + FD->isTargetVersionMultiVersion()) { const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI); std::string MangledName = getMangledNameImpl( @@ -4393,8 +4395,18 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) { // a separate resolver). std::string ResolverName = MangledName; if (getTarget().supportsIFunc()) { - if (!FD->isTargetClonesMultiVersion()) + switch (FD->getMultiVersionKind()) { + case MultiVersionKind::None: + llvm_unreachable("unexpected MultiVersionKind::None for resolver"); + case MultiVersionKind::Target: + case MultiVersionKind::CPUSpecific: + case MultiVersionKind::CPUDispatch: ResolverName += ".ifunc"; + break; + case MultiVersionKind::TargetClones: + case MultiVersionKind::TargetVersion: + break; + } } else if (FD->isTargetMultiVersion()) { ResolverName += ".resolver"; } diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 0c43317642bca458172abfb54aa5a2cd7693d730..93fe76eb9903e9ca6c9c25ce78f9c329a65b0f65 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -95,9 +95,6 @@ void CoverageSourceInfo::updateNextTokLoc(SourceLocation Loc) { } namespace { -using MCDCConditionID = CounterMappingRegion::MCDCConditionID; -using MCDCParameters = CounterMappingRegion::MCDCParameters; - /// A region of source code that can be mapped to a counter. class SourceMappingRegion { /// Primary Counter that is also used for Branch Regions for "True" branches. @@ -107,7 +104,7 @@ class SourceMappingRegion { std::optional FalseCount; /// Parameters used for Modified Condition/Decision Coverage - MCDCParameters MCDCParams; + mcdc::Parameters MCDCParams; /// The region's starting location. std::optional LocStart; @@ -131,7 +128,7 @@ public: SkippedRegion(false) {} SourceMappingRegion(Counter Count, std::optional FalseCount, - MCDCParameters MCDCParams, + mcdc::Parameters MCDCParams, std::optional LocStart, std::optional LocEnd, bool GapRegion = false) @@ -139,7 +136,7 @@ public: LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion), SkippedRegion(false) {} - SourceMappingRegion(MCDCParameters MCDCParams, + SourceMappingRegion(mcdc::Parameters MCDCParams, std::optional LocStart, std::optional LocEnd) : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd), @@ -185,9 +182,19 @@ public: bool isBranch() const { return FalseCount.has_value(); } - bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; } + bool isMCDCDecision() const { + const auto *DecisionParams = + std::get_if(&MCDCParams); + assert(!DecisionParams || DecisionParams->NumConditions > 0); + return DecisionParams; + } + + const auto &getMCDCDecisionParams() const { + return CounterMappingRegion::getParams( + MCDCParams); + } - const MCDCParameters &getMCDCParams() const { return MCDCParams; } + const mcdc::Parameters &getMCDCParams() const { return MCDCParams; } }; /// Spelling locations for the start and end of a source region. @@ -483,13 +490,13 @@ public: SR.ColumnEnd)); } else if (Region.isBranch()) { MappingRegions.push_back(CounterMappingRegion::makeBranchRegion( - Region.getCounter(), Region.getFalseCounter(), - Region.getMCDCParams(), *CovFileID, SR.LineStart, SR.ColumnStart, - SR.LineEnd, SR.ColumnEnd)); + Region.getCounter(), Region.getFalseCounter(), *CovFileID, + SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd, + Region.getMCDCParams())); } else if (Region.isMCDCDecision()) { MappingRegions.push_back(CounterMappingRegion::makeDecisionRegion( - Region.getMCDCParams(), *CovFileID, SR.LineStart, SR.ColumnStart, - SR.LineEnd, SR.ColumnEnd)); + Region.getMCDCDecisionParams(), *CovFileID, SR.LineStart, + SR.ColumnStart, SR.LineEnd, SR.ColumnEnd)); } else { MappingRegions.push_back(CounterMappingRegion::makeRegion( Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart, @@ -587,8 +594,8 @@ struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder { struct MCDCCoverageBuilder { struct DecisionIDPair { - MCDCConditionID TrueID = 0; - MCDCConditionID FalseID = 0; + mcdc::ConditionID TrueID = 0; + mcdc::ConditionID FalseID = 0; }; /// The AST walk recursively visits nested logical-AND or logical-OR binary @@ -682,9 +689,9 @@ private: CodeGenModule &CGM; llvm::SmallVector DecisionStack; - llvm::DenseMap &CondIDs; + llvm::DenseMap &CondIDs; llvm::DenseMap &MCDCBitmapMap; - MCDCConditionID NextID = 1; + mcdc::ConditionID NextID = 1; bool NotMapped = false; /// Represent a sentinel value of [0,0] for the bottom of DecisionStack. @@ -696,9 +703,10 @@ private: } public: - MCDCCoverageBuilder(CodeGenModule &CGM, - llvm::DenseMap &CondIDMap, - llvm::DenseMap &MCDCBitmapMap) + MCDCCoverageBuilder( + CodeGenModule &CGM, + llvm::DenseMap &CondIDMap, + llvm::DenseMap &MCDCBitmapMap) : CGM(CGM), DecisionStack(1, DecisionStackSentinel), CondIDs(CondIDMap), MCDCBitmapMap(MCDCBitmapMap) {} @@ -713,12 +721,12 @@ public: bool isBuilding() const { return (NextID > 1); } /// Set the given condition's ID. - void setCondID(const Expr *Cond, MCDCConditionID ID) { + void setCondID(const Expr *Cond, mcdc::ConditionID ID) { CondIDs[CodeGenFunction::stripCond(Cond)] = ID; } /// Return the ID of a given condition. - MCDCConditionID getCondID(const Expr *Cond) const { + mcdc::ConditionID getCondID(const Expr *Cond) const { auto I = CondIDs.find(CodeGenFunction::stripCond(Cond)); if (I == CondIDs.end()) return 0; @@ -755,7 +763,7 @@ public: setCondID(E->getLHS(), NextID++); // Assign a ID+1 for the RHS. - MCDCConditionID RHSid = NextID++; + mcdc::ConditionID RHSid = NextID++; setCondID(E->getRHS(), RHSid); // Push the LHS decision IDs onto the DecisionStack. @@ -865,8 +873,7 @@ struct CounterCoverageMappingBuilder std::optional StartLoc = std::nullopt, std::optional EndLoc = std::nullopt, std::optional FalseCount = std::nullopt, - MCDCConditionID ID = 0, MCDCConditionID TrueID = 0, - MCDCConditionID FalseID = 0) { + const mcdc::Parameters &BranchParams = std::monostate()) { if (StartLoc && !FalseCount) { MostRecentLocation = *StartLoc; @@ -885,9 +892,7 @@ struct CounterCoverageMappingBuilder StartLoc = std::nullopt; if (EndLoc && EndLoc->isInvalid()) EndLoc = std::nullopt; - RegionStack.emplace_back(Count, FalseCount, - MCDCParameters{0, 0, ID, TrueID, FalseID}, - StartLoc, EndLoc); + RegionStack.emplace_back(Count, FalseCount, BranchParams, StartLoc, EndLoc); return RegionStack.size() - 1; } @@ -896,8 +901,8 @@ struct CounterCoverageMappingBuilder std::optional StartLoc = std::nullopt, std::optional EndLoc = std::nullopt) { - RegionStack.emplace_back(MCDCParameters{BitmapIdx, Conditions}, StartLoc, - EndLoc); + RegionStack.emplace_back(mcdc::DecisionParameters{BitmapIdx, Conditions}, + StartLoc, EndLoc); return RegionStack.size() - 1; } @@ -1042,9 +1047,11 @@ struct CounterCoverageMappingBuilder // function's SourceRegions) because it doesn't apply to any other source // code other than the Condition. if (CodeGenFunction::isInstrumentedCondition(C)) { - MCDCConditionID ID = MCDCBuilder.getCondID(C); - MCDCConditionID TrueID = IDPair.TrueID; - MCDCConditionID FalseID = IDPair.FalseID; + mcdc::Parameters BranchParams; + mcdc::ConditionID ID = MCDCBuilder.getCondID(C); + if (ID > 0) + BranchParams = + mcdc::BranchParameters{ID, IDPair.TrueID, IDPair.FalseID}; // If a condition can fold to true or false, the corresponding branch // will be removed. Create a region with both counters hard-coded to @@ -1054,11 +1061,11 @@ struct CounterCoverageMappingBuilder // CodeGenFunction.c always returns false, but that is very heavy-handed. if (ConditionFoldsToBool(C)) popRegions(pushRegion(Counter::getZero(), getStart(C), getEnd(C), - Counter::getZero(), ID, TrueID, FalseID)); + Counter::getZero(), BranchParams)); else // Otherwise, create a region with the True counter and False counter. - popRegions(pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt, ID, - TrueID, FalseID)); + popRegions(pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt, + BranchParams)); } } @@ -1149,12 +1156,9 @@ struct CounterCoverageMappingBuilder // we've seen this region. if (StartLocs.insert(Loc).second) { if (I.isBranch()) - SourceRegions.emplace_back( - I.getCounter(), I.getFalseCounter(), - MCDCParameters{0, 0, I.getMCDCParams().ID, - I.getMCDCParams().TrueID, - I.getMCDCParams().FalseID}, - Loc, getEndOfFileOrMacro(Loc), I.isBranch()); + SourceRegions.emplace_back(I.getCounter(), I.getFalseCounter(), + I.getMCDCParams(), Loc, + getEndOfFileOrMacro(Loc), I.isBranch()); else SourceRegions.emplace_back(I.getCounter(), Loc, getEndOfFileOrMacro(Loc)); @@ -1338,7 +1342,7 @@ struct CounterCoverageMappingBuilder CoverageMappingModuleGen &CVM, llvm::DenseMap &CounterMap, llvm::DenseMap &MCDCBitmapMap, - llvm::DenseMap &CondIDMap, + llvm::DenseMap &CondIDMap, SourceManager &SM, const LangOptions &LangOpts) : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap), MCDCBitmapMap(MCDCBitmapMap), @@ -2120,9 +2124,10 @@ static void dump(llvm::raw_ostream &OS, StringRef FunctionName, OS << "File " << R.FileID << ", " << R.LineStart << ":" << R.ColumnStart << " -> " << R.LineEnd << ":" << R.ColumnEnd << " = "; - if (R.Kind == CounterMappingRegion::MCDCDecisionRegion) { - OS << "M:" << R.MCDCParams.BitmapIdx; - OS << ", C:" << R.MCDCParams.NumConditions; + if (const auto *DecisionParams = + std::get_if(&R.MCDCParams)) { + OS << "M:" << DecisionParams->BitmapIdx; + OS << ", C:" << DecisionParams->NumConditions; } else { Ctx.dump(R.Count, OS); @@ -2133,9 +2138,10 @@ static void dump(llvm::raw_ostream &OS, StringRef FunctionName, } } - if (R.Kind == CounterMappingRegion::MCDCBranchRegion) { - OS << " [" << R.MCDCParams.ID << "," << R.MCDCParams.TrueID; - OS << "," << R.MCDCParams.FalseID << "] "; + if (const auto *BranchParams = + std::get_if(&R.MCDCParams)) { + OS << " [" << BranchParams->ID << "," << BranchParams->TrueID; + OS << "," << BranchParams->FalseID << "] "; } if (R.Kind == CounterMappingRegion::ExpansionRegion) diff --git a/clang/lib/CodeGen/MacroPPCallbacks.cpp b/clang/lib/CodeGen/MacroPPCallbacks.cpp index 8589869f6e2fb54ea681fce51c29ea94af2fd95e..c5d1e3ad5a20541eac3de672dc9d54cfab940980 100644 --- a/clang/lib/CodeGen/MacroPPCallbacks.cpp +++ b/clang/lib/CodeGen/MacroPPCallbacks.cpp @@ -168,8 +168,8 @@ void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason, void MacroPPCallbacks::InclusionDirective( SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, - StringRef SearchPath, StringRef RelativePath, const Module *Imported, - SrcMgr::CharacteristicKind FileType) { + StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) { // Record the line location of the current included file. LastHashLoc = HashLoc; diff --git a/clang/lib/CodeGen/MacroPPCallbacks.h b/clang/lib/CodeGen/MacroPPCallbacks.h index 5af177d0c3fa21b208619c237c08f390a34b635a..5f468648da04481938ecfc85cb89739e769d638b 100644 --- a/clang/lib/CodeGen/MacroPPCallbacks.h +++ b/clang/lib/CodeGen/MacroPPCallbacks.h @@ -102,7 +102,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override; /// Hook called whenever a macro definition is seen. diff --git a/clang/lib/Driver/ToolChains/Arch/Sparc.cpp b/clang/lib/Driver/ToolChains/Arch/Sparc.cpp index 22e583021515e5de9f367ee4d04bef787c72b575..ae1a4ba7882627f639f18bff721309ac0b78184f 100644 --- a/clang/lib/Driver/ToolChains/Arch/Sparc.cpp +++ b/clang/lib/Driver/ToolChains/Arch/Sparc.cpp @@ -178,4 +178,85 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args, else Features.push_back("-hard-quad-float"); } + + if (Args.hasArg(options::OPT_ffixed_g1)) + Features.push_back("+reserve-g1"); + + if (Args.hasArg(options::OPT_ffixed_g2)) + Features.push_back("+reserve-g2"); + + if (Args.hasArg(options::OPT_ffixed_g3)) + Features.push_back("+reserve-g3"); + + if (Args.hasArg(options::OPT_ffixed_g4)) + Features.push_back("+reserve-g4"); + + if (Args.hasArg(options::OPT_ffixed_g5)) + Features.push_back("+reserve-g5"); + + if (Args.hasArg(options::OPT_ffixed_g6)) + Features.push_back("+reserve-g6"); + + if (Args.hasArg(options::OPT_ffixed_g7)) + Features.push_back("+reserve-g7"); + + if (Args.hasArg(options::OPT_ffixed_o0)) + Features.push_back("+reserve-o0"); + + if (Args.hasArg(options::OPT_ffixed_o1)) + Features.push_back("+reserve-o1"); + + if (Args.hasArg(options::OPT_ffixed_o2)) + Features.push_back("+reserve-o2"); + + if (Args.hasArg(options::OPT_ffixed_o3)) + Features.push_back("+reserve-o3"); + + if (Args.hasArg(options::OPT_ffixed_o4)) + Features.push_back("+reserve-o4"); + + if (Args.hasArg(options::OPT_ffixed_o5)) + Features.push_back("+reserve-o5"); + + if (Args.hasArg(options::OPT_ffixed_l0)) + Features.push_back("+reserve-l0"); + + if (Args.hasArg(options::OPT_ffixed_l1)) + Features.push_back("+reserve-l1"); + + if (Args.hasArg(options::OPT_ffixed_l2)) + Features.push_back("+reserve-l2"); + + if (Args.hasArg(options::OPT_ffixed_l3)) + Features.push_back("+reserve-l3"); + + if (Args.hasArg(options::OPT_ffixed_l4)) + Features.push_back("+reserve-l4"); + + if (Args.hasArg(options::OPT_ffixed_l5)) + Features.push_back("+reserve-l5"); + + if (Args.hasArg(options::OPT_ffixed_l6)) + Features.push_back("+reserve-l6"); + + if (Args.hasArg(options::OPT_ffixed_l7)) + Features.push_back("+reserve-l7"); + + if (Args.hasArg(options::OPT_ffixed_i0)) + Features.push_back("+reserve-i0"); + + if (Args.hasArg(options::OPT_ffixed_i1)) + Features.push_back("+reserve-i1"); + + if (Args.hasArg(options::OPT_ffixed_i2)) + Features.push_back("+reserve-i2"); + + if (Args.hasArg(options::OPT_ffixed_i3)) + Features.push_back("+reserve-i3"); + + if (Args.hasArg(options::OPT_ffixed_i4)) + Features.push_back("+reserve-i4"); + + if (Args.hasArg(options::OPT_ffixed_i5)) + Features.push_back("+reserve-i5"); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 942ebbc410607804bbae79fe2b993c1890c36828..4459d86e77d5d95b3c0b0f943cce9fe1b49d8b7a 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2778,6 +2778,26 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, LangOptions::ComplexRangeKind Range = LangOptions::ComplexRangeKind::CX_None; std::string ComplexRangeStr = ""; + // Lambda to set fast-math options. This is also used by -ffp-model=fast + auto applyFastMath = [&]() { + HonorINFs = false; + HonorNaNs = false; + MathErrno = false; + AssociativeMath = true; + ReciprocalMath = true; + ApproxFunc = true; + SignedZeros = false; + TrappingMath = false; + RoundingFPMath = false; + FPExceptionBehavior = ""; + // If fast-math is set then set the fp-contract mode to fast. + FPContract = "fast"; + // ffast-math enables limited range rules for complex multiplication and + // division. + Range = LangOptions::ComplexRangeKind::CX_Limited; + SeenUnsafeMathModeOption = true; + }; + if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) { CmdArgs.push_back("-mlimit-float-precision"); CmdArgs.push_back(A->getValue()); @@ -2842,9 +2862,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, << Args.MakeArgString("-ffp-model=" + FPModel) << Args.MakeArgString("-ffp-model=" + Val); if (Val.equals("fast")) { - optID = options::OPT_ffast_math; FPModel = Val; - FPContract = "fast"; + applyFastMath(); } else if (Val.equals("precise")) { optID = options::OPT_ffp_contract; FPModel = Val; @@ -3061,22 +3080,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, continue; [[fallthrough]]; case options::OPT_ffast_math: { - HonorINFs = false; - HonorNaNs = false; - MathErrno = false; - AssociativeMath = true; - ReciprocalMath = true; - ApproxFunc = true; - SignedZeros = false; - TrappingMath = false; - RoundingFPMath = false; - FPExceptionBehavior = ""; - // If fast-math is set then set the fp-contract mode to fast. - FPContract = "fast"; - SeenUnsafeMathModeOption = true; - // ffast-math enables fortran rules for complex multiplication and - // division. - Range = LangOptions::ComplexRangeKind::CX_Limited; + applyFastMath(); break; } case options::OPT_fno_fast_math: diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index fae8ad1a958ade0e469e343c5c8ed558cc2976ae..cc1219d69d9910d24b7cc3b9d153665024026c3f 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -1902,6 +1902,7 @@ getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver, "TVOS_DEPLOYMENT_TARGET", "WATCHOS_DEPLOYMENT_TARGET", "DRIVERKIT_DEPLOYMENT_TARGET", + "XROS_DEPLOYMENT_TARGET" }; static_assert(std::size(EnvVars) == Darwin::LastDarwinPlatform + 1, "Missing platform"); @@ -1914,14 +1915,15 @@ getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver, // default platform. if (!Targets[Darwin::MacOS].empty() && (!Targets[Darwin::IPhoneOS].empty() || - !Targets[Darwin::WatchOS].empty() || !Targets[Darwin::TvOS].empty())) { + !Targets[Darwin::WatchOS].empty() || !Targets[Darwin::TvOS].empty() || + !Targets[Darwin::XROS].empty())) { if (Triple.getArch() == llvm::Triple::arm || Triple.getArch() == llvm::Triple::aarch64 || Triple.getArch() == llvm::Triple::thumb) Targets[Darwin::MacOS] = ""; else Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] = - Targets[Darwin::TvOS] = ""; + Targets[Darwin::TvOS] = Targets[Darwin::XROS] = ""; } else { // Don't allow conflicts in any other platform. unsigned FirstTarget = std::size(Targets); diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h index 5e60b0841d6d5f22a8725f206660b79efc60dfcd..10d4b69e5d5f10dacd40442f20930ca0aeca719f 100644 --- a/clang/lib/Driver/ToolChains/Darwin.h +++ b/clang/lib/Driver/ToolChains/Darwin.h @@ -300,7 +300,7 @@ public: WatchOS, DriverKit, XROS, - LastDarwinPlatform = DriverKit + LastDarwinPlatform = XROS }; enum DarwinEnvironmentKind { NativeEnvironment, diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 23da08aa593f2db3989d142116189fde6840ed31..6168b42dc78292d9d3aebf8a809c5257a0cf502f 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -249,6 +249,20 @@ void Flang::AddRISCVTargetArgs(const ArgList &Args, } } +void Flang::AddX86_64TargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) { + StringRef Value = A->getValue(); + if (Value == "intel" || Value == "att") { + CmdArgs.push_back(Args.MakeArgString("-mllvm")); + CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value)); + } else { + getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument) + << A->getSpelling() << Value; + } + } +} + static void addVSDefines(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { @@ -374,6 +388,7 @@ void Flang::addTargetOptions(const ArgList &Args, break; case llvm::Triple::x86_64: getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false); + AddX86_64TargetArgs(Args, CmdArgs); break; } diff --git a/clang/lib/Driver/ToolChains/Flang.h b/clang/lib/Driver/ToolChains/Flang.h index ec2e545a1d0b5cfb109ac506b1345c06ff0153af..9f5e26b8608324def4e7cf3a47e2c7d4136a6c4a 100644 --- a/clang/lib/Driver/ToolChains/Flang.h +++ b/clang/lib/Driver/ToolChains/Flang.h @@ -77,6 +77,13 @@ private: void AddRISCVTargetArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + /// Add specific options for X86_64 target. + /// + /// \param [in] Args The list of input driver arguments + /// \param [out] CmdArgs The list of output command arguments + void AddX86_64TargetArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const; + /// Extract offload options from the driver arguments and add them to /// the command arguments. /// \param [in] C The current compilation for the driver invocation diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 7fd04b23abdca6c16e4df21f648a4f510fb217c5..0b2ef97af44d83ede4536d08abf65c4a88cc3500 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -569,9 +569,8 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { return true; } } - return Style.AlwaysBreakTemplateDeclarations != FormatStyle::BTDS_No && - (Style.AlwaysBreakTemplateDeclarations != - FormatStyle::BTDS_Leave || + return Style.BreakTemplateDeclarations != FormatStyle::BTDS_No && + (Style.BreakTemplateDeclarations != FormatStyle::BTDS_Leave || Current.NewlinesBefore > 0); } if (Previous.is(TT_FunctionAnnotationRParen) && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index c5714af155f0b5135851365252c7732b3eb2c7ad..8efc42e0576cf980e3ed81583682ff9717d5e0a0 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -877,6 +877,10 @@ template <> struct MappingTraits { if (!IO.outputting()) { IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines); IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine); + IO.mapOptional("AlwaysBreakAfterReturnType", + Style.AlwaysBreakAfterReturnType); + IO.mapOptional("AlwaysBreakTemplateDeclarations", + Style.BreakTemplateDeclarations); IO.mapOptional("BreakBeforeInheritanceComma", BreakBeforeInheritanceComma); IO.mapOptional("BreakConstructorInitializersBeforeComma", @@ -939,12 +943,8 @@ template <> struct MappingTraits { Style.AllowShortLoopsOnASingleLine); IO.mapOptional("AlwaysBreakAfterDefinitionReturnType", Style.AlwaysBreakAfterDefinitionReturnType); - IO.mapOptional("AlwaysBreakAfterReturnType", - Style.AlwaysBreakAfterReturnType); IO.mapOptional("AlwaysBreakBeforeMultilineStrings", Style.AlwaysBreakBeforeMultilineStrings); - IO.mapOptional("AlwaysBreakTemplateDeclarations", - Style.AlwaysBreakTemplateDeclarations); IO.mapOptional("AttributeMacros", Style.AttributeMacros); IO.mapOptional("BinPackArguments", Style.BinPackArguments); IO.mapOptional("BinPackParameters", Style.BinPackParameters); @@ -957,6 +957,7 @@ template <> struct MappingTraits { IO.mapOptional("BreakAfterAttributes", Style.BreakAfterAttributes); IO.mapOptional("BreakAfterJavaFieldAnnotations", Style.BreakAfterJavaFieldAnnotations); + IO.mapOptional("BreakAfterReturnType", Style.AlwaysBreakAfterReturnType); IO.mapOptional("BreakArrays", Style.BreakArrays); IO.mapOptional("BreakBeforeBinaryOperators", Style.BreakBeforeBinaryOperators); @@ -971,6 +972,8 @@ template <> struct MappingTraits { Style.BreakConstructorInitializers); IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList); IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals); + IO.mapOptional("BreakTemplateDeclarations", + Style.BreakTemplateDeclarations); IO.mapOptional("ColumnLimit", Style.ColumnLimit); IO.mapOptional("CommentPragmas", Style.CommentPragmas); IO.mapOptional("CompactNamespaces", Style.CompactNamespaces); @@ -1439,7 +1442,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; - LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine; + LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine; LLVMStyle.AttributeMacros.push_back("__capability"); LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both; LLVMStyle.BinPackArguments = true; @@ -1629,7 +1632,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { FormatStyle::SIS_WithoutElse; GoogleStyle.AllowShortLoopsOnASingleLine = true; GoogleStyle.AlwaysBreakBeforeMultilineStrings = true; - GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; + GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes; GoogleStyle.DerivePointerAlignment = true; GoogleStyle.IncludeStyle.IncludeCategories = {{"^", 2, 0, false}, {"^<.*\\.h>", 1, 0, false}, @@ -1822,7 +1825,7 @@ FormatStyle getMozillaStyle() { MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel; MozillaStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_TopLevel; - MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; + MozillaStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes; MozillaStyle.BinPackParameters = false; MozillaStyle.BinPackArguments = false; MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla; diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index bace91b5f99b4dfed0da7d495a39a950333822cd..0c1dce7a294082834b994a9b3c26645f29515c49 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -150,7 +150,17 @@ namespace format { TYPE(StructuredBindingLSquare) \ TYPE(TableGenBangOperator) \ TYPE(TableGenCondOperator) \ + TYPE(TableGenCondOperatorColon) \ + TYPE(TableGenCondOperatorComma) \ + TYPE(TableGenDAGArgCloser) \ + TYPE(TableGenDAGArgListColon) \ + TYPE(TableGenDAGArgListComma) \ + TYPE(TableGenDAGArgOpener) \ + TYPE(TableGenListCloser) \ + TYPE(TableGenListOpener) \ TYPE(TableGenMultiLineString) \ + TYPE(TableGenTrailingPasteOperator) \ + TYPE(TableGenValueSuffix) \ TYPE(TemplateCloser) \ TYPE(TemplateOpener) \ TYPE(TemplateString) \ diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp index a87d0ba3dbbf9b100fa6586ac805b55fdbf77202..492e7e96dd22e675580aec4ac9056936fcc66eee 100644 --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -13,11 +13,7 @@ //===----------------------------------------------------------------------===// #include "FormatTokenLexer.h" -#include "FormatToken.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Format/Format.h" -#include "llvm/Support/Regex.h" +#include "TokenAnalyzer.h" namespace clang { namespace format { @@ -28,12 +24,12 @@ FormatTokenLexer::FormatTokenLexer( llvm::SpecificBumpPtrAllocator &Allocator, IdentifierTable &IdentTable) : FormatTok(nullptr), IsFirstToken(true), StateStack({LexerState::NORMAL}), - Column(Column), TrailingWhitespace(0), - LangOpts(getFormattingLangOpts(Style)), SourceMgr(SourceMgr), ID(ID), + Column(Column), TrailingWhitespace(0), SourceMgr(SourceMgr), ID(ID), Style(Style), IdentTable(IdentTable), Keywords(IdentTable), Encoding(Encoding), Allocator(Allocator), FirstInLineIndex(0), FormattingDisabled(false), MacroBlockBeginRegex(Style.MacroBlockBegin), MacroBlockEndRegex(Style.MacroBlockEnd) { + assert(LangOpts.CPlusPlus); Lex.reset(new Lexer(ID, SourceMgr.getBufferOrFake(ID), SourceMgr, LangOpts)); Lex->SetKeepWhitespaceMode(true); @@ -816,7 +812,7 @@ void FormatTokenLexer::handleTableGenMultilineString() { auto CloseOffset = Lex->getBuffer().find("}]", OpenOffset); if (CloseOffset == StringRef::npos) return; - auto Text = Lex->getBuffer().substr(OpenOffset, CloseOffset + 2); + auto Text = Lex->getBuffer().substr(OpenOffset, CloseOffset - OpenOffset + 2); MultiLineString->TokenText = Text; resetLexer(SourceMgr.getFileOffset( Lex->getSourceLocation(Lex->getBufferLocation() - 2 + Text.size()))); @@ -1442,7 +1438,7 @@ void FormatTokenLexer::readRawToken(FormatToken &Tok) { void FormatTokenLexer::resetLexer(unsigned Offset) { StringRef Buffer = SourceMgr.getBufferData(ID); - LangOpts = getFormattingLangOpts(Style); + assert(LangOpts.CPlusPlus); Lex.reset(new Lexer(SourceMgr.getLocForStartOfFile(ID), LangOpts, Buffer.begin(), Buffer.begin() + Offset, Buffer.end())); Lex->SetKeepWhitespaceMode(true); diff --git a/clang/lib/Format/FormatTokenLexer.h b/clang/lib/Format/FormatTokenLexer.h index 65dd733bd53352a4b1be96b360090fde180fba50..ca91c5b7d20d4eab0b949eb80425141b3c2b924e 100644 --- a/clang/lib/Format/FormatTokenLexer.h +++ b/clang/lib/Format/FormatTokenLexer.h @@ -17,14 +17,9 @@ #include "Encoding.h" #include "FormatToken.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Format/Format.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringSet.h" -#include "llvm/Support/Regex.h" #include @@ -120,7 +115,6 @@ private: unsigned Column; unsigned TrailingWhitespace; std::unique_ptr Lex; - LangOptions LangOpts; const SourceManager &SourceMgr; FileID ID; const FormatStyle &Style; diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp index 87823ae32b11387c217ffb0e4a997310bf4511a7..3c2ceddd5599cf027d9598d12137f478f57b4988 100644 --- a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp +++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp @@ -79,7 +79,7 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env, AffectedRangeManager AffectedRangeMgr(SourceMgr, Env.getCharRanges()); const auto ID = Env.getFileID(); - const auto LangOpts = getFormattingLangOpts(Style); + assert(LangOpts.CPlusPlus); Lexer Lex(ID, SourceMgr.getBufferOrFake(ID), SourceMgr, LangOpts); Lex.SetCommentRetentionState(true); diff --git a/clang/lib/Format/TokenAnalyzer.cpp b/clang/lib/Format/TokenAnalyzer.cpp index bd648c430f9b0a460b9901018efaf341e02e848e..f9d1fdb86f1ae91885f167d3ba241bd0eca688a5 100644 --- a/clang/lib/Format/TokenAnalyzer.cpp +++ b/clang/lib/Format/TokenAnalyzer.cpp @@ -35,6 +35,8 @@ namespace clang { namespace format { +LangOptions LangOpts; + // FIXME: Instead of printing the diagnostic we should store it and have a // better way to return errors through the format APIs. class FatalDiagnosticConsumer : public DiagnosticConsumer { @@ -99,9 +101,11 @@ TokenAnalyzer::TokenAnalyzer(const Environment &Env, const FormatStyle &Style) std::pair TokenAnalyzer::process(bool SkipAnnotation) { + LangOpts = getFormattingLangOpts(Style); + tooling::Replacements Result; llvm::SpecificBumpPtrAllocator Allocator; - IdentifierTable IdentTable(getFormattingLangOpts(Style)); + IdentifierTable IdentTable(LangOpts); FormatTokenLexer Lex(Env.getSourceManager(), Env.getFileID(), Env.getFirstStartColumn(), Style, Encoding, Allocator, IdentTable); diff --git a/clang/lib/Format/TokenAnalyzer.h b/clang/lib/Format/TokenAnalyzer.h index 4086dab1c94c3ad6a11fba34ad271e196392829d..18c1431eb3761225753d0001fb00f6b69a710939 100644 --- a/clang/lib/Format/TokenAnalyzer.h +++ b/clang/lib/Format/TokenAnalyzer.h @@ -34,6 +34,8 @@ namespace clang { namespace format { +extern LangOptions LangOpts; + class Environment { public: // This sets up an virtual file system with file \p FileName containing the diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index cec56fad5315659858ace032bddf4ff1ab128449..b9a000faae7cf7ba945e6b3d741b0898b632322a 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -256,6 +256,18 @@ private: } } } + if (Style.isTableGen()) { + if (CurrentToken->isOneOf(tok::comma, tok::equal)) { + // They appear as separators. Unless they are not in class definition. + next(); + continue; + } + // In angle, there must be Value like tokens. Types are also able to be + // parsed in the same way with Values. + if (!parseTableGenValue()) + return false; + continue; + } if (!consumeToken()) return false; } @@ -388,6 +400,28 @@ private: Contexts.back().IsExpression = !IsForOrCatch; } + if (Style.isTableGen()) { + if (FormatToken *Prev = OpeningParen.Previous) { + if (Prev->is(TT_TableGenCondOperator)) { + Contexts.back().IsTableGenCondOpe = true; + Contexts.back().IsExpression = true; + } else if (Contexts.size() > 1 && + Contexts[Contexts.size() - 2].IsTableGenBangOpe) { + // Hack to handle bang operators. The parent context's flag + // was set by parseTableGenSimpleValue(). + // We have to specify the context outside because the prev of "(" may + // be ">", not the bang operator in this case. + Contexts.back().IsTableGenBangOpe = true; + Contexts.back().IsExpression = true; + } else { + // Otherwise, this paren seems DAGArg. + if (!parseTableGenDAGArg()) + return false; + return parseTableGenDAGArgAndList(&OpeningParen); + } + } + } + // Infer the role of the l_paren based on the previous token if we haven't // detected one yet. if (PrevNonComment && OpeningParen.is(TT_Unknown)) { @@ -549,6 +583,22 @@ private: if (CurrentToken->is(tok::comma)) Contexts.back().CanBeExpression = true; + if (Style.isTableGen()) { + if (CurrentToken->is(tok::comma)) { + if (Contexts.back().IsTableGenCondOpe) + CurrentToken->setType(TT_TableGenCondOperatorComma); + next(); + } else if (CurrentToken->is(tok::colon)) { + if (Contexts.back().IsTableGenCondOpe) + CurrentToken->setType(TT_TableGenCondOperatorColon); + next(); + } + // In TableGen there must be Values in parens. + if (!parseTableGenValue()) + return false; + continue; + } + FormatToken *Tok = CurrentToken; if (!consumeToken()) return false; @@ -803,6 +853,8 @@ private: if (Left->BlockParameterCount > 1) Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 0; } + if (Style.isTableGen() && Left->is(TT_TableGenListOpener)) + CurrentToken->setType(TT_TableGenListCloser); next(); return true; } @@ -833,6 +885,19 @@ private: Left->setType(TT_ArrayInitializerLSquare); } FormatToken *Tok = CurrentToken; + if (Style.isTableGen()) { + if (CurrentToken->isOneOf(tok::comma, tok::minus, tok::ellipsis)) { + // '-' and '...' appears as a separator in slice. + next(); + } else { + // In TableGen there must be a list of Values in square brackets. + // It must be ValueList or SliceElements. + if (!parseTableGenValue()) + return false; + } + updateParameterCount(Left, Tok); + continue; + } if (!consumeToken()) return false; updateParameterCount(Left, Tok); @@ -840,6 +905,193 @@ private: return false; } + void skipToNextNonComment() { + next(); + while (CurrentToken && CurrentToken->is(tok::comment)) + next(); + } + + // Simplified parser for TableGen Value. Returns true on success. + // It consists of SimpleValues, SimpleValues with Suffixes, and Value followed + // by '#', paste operator. + // There also exists the case the Value is parsed as NameValue. + // In this case, the Value ends if '{' is found. + bool parseTableGenValue(bool ParseNameMode = false) { + if (!CurrentToken) + return false; + while (CurrentToken->is(tok::comment)) + next(); + if (!parseTableGenSimpleValue()) + return false; + if (!CurrentToken) + return true; + // Value "#" [Value] + if (CurrentToken->is(tok::hash)) { + if (CurrentToken->Next && + CurrentToken->Next->isOneOf(tok::colon, tok::semi, tok::l_brace)) { + // Trailing paste operator. + // These are only the allowed cases in TGParser::ParseValue(). + CurrentToken->setType(TT_TableGenTrailingPasteOperator); + next(); + return true; + } + FormatToken *HashTok = CurrentToken; + skipToNextNonComment(); + HashTok->setType(TT_Unknown); + if (!parseTableGenValue(ParseNameMode)) + return false; + } + // In name mode, '{' is regarded as the end of the value. + // See TGParser::ParseValue in TGParser.cpp + if (ParseNameMode && CurrentToken->is(tok::l_brace)) + return true; + // These tokens indicates this is a value with suffixes. + if (CurrentToken->isOneOf(tok::l_brace, tok::l_square, tok::period)) { + CurrentToken->setType(TT_TableGenValueSuffix); + FormatToken *Suffix = CurrentToken; + skipToNextNonComment(); + if (Suffix->is(tok::l_square)) + return parseSquare(); + if (Suffix->is(tok::l_brace)) { + Scopes.push_back(getScopeType(*Suffix)); + return parseBrace(); + } + } + return true; + } + + // TokVarName ::= "$" ualpha (ualpha | "0"..."9")* + // Appears as a part of DagArg. + // This does not change the current token on fail. + bool tryToParseTableGenTokVar() { + if (!CurrentToken) + return false; + if (CurrentToken->is(tok::identifier) && + CurrentToken->TokenText.front() == '$') { + skipToNextNonComment(); + return true; + } + return false; + } + + // DagArg ::= Value [":" TokVarName] | TokVarName + // Appears as a part of SimpleValue6. + bool parseTableGenDAGArg() { + if (tryToParseTableGenTokVar()) + return true; + if (parseTableGenValue()) { + if (CurrentToken && CurrentToken->is(tok::colon)) { + CurrentToken->setType(TT_TableGenDAGArgListColon); + skipToNextNonComment(); + return tryToParseTableGenTokVar(); + } + return true; + } + return false; + } + + // SimpleValue6 ::= "(" DagArg [DagArgList] ")" + // This parses SimpleValue 6's inside part of "(" ")" + bool parseTableGenDAGArgAndList(FormatToken *Opener) { + if (!parseTableGenDAGArg()) + return false; + // Parse the [DagArgList] part + bool FirstDAGArgListElm = true; + while (CurrentToken) { + if (!FirstDAGArgListElm && CurrentToken->is(tok::comma)) { + CurrentToken->setType(TT_TableGenDAGArgListComma); + skipToNextNonComment(); + } + if (CurrentToken && CurrentToken->is(tok::r_paren)) { + CurrentToken->setType(TT_TableGenDAGArgCloser); + Opener->MatchingParen = CurrentToken; + CurrentToken->MatchingParen = Opener; + skipToNextNonComment(); + return true; + } + if (!parseTableGenDAGArg()) + return false; + FirstDAGArgListElm = false; + } + return false; + } + + bool parseTableGenSimpleValue() { + assert(Style.isTableGen()); + if (!CurrentToken) + return false; + FormatToken *Tok = CurrentToken; + skipToNextNonComment(); + // SimpleValue 1, 2, 3: Literals + if (Tok->isOneOf(tok::numeric_constant, tok::string_literal, + TT_TableGenMultiLineString, tok::kw_true, tok::kw_false, + tok::question, tok::kw_int)) { + return true; + } + // SimpleValue 4: ValueList, Type + if (Tok->is(tok::l_brace)) { + Scopes.push_back(getScopeType(*Tok)); + return parseBrace(); + } + // SimpleValue 5: List initializer + if (Tok->is(tok::l_square)) { + Tok->setType(TT_TableGenListOpener); + if (!parseSquare()) + return false; + if (Tok->is(tok::less)) { + CurrentToken->setType(TT_TemplateOpener); + return parseAngle(); + } + return true; + } + // SimpleValue 6: DAGArg [DAGArgList] + // SimpleValue6 ::= "(" DagArg [DagArgList] ")" + if (Tok->is(tok::l_paren)) { + Tok->setType(TT_TableGenDAGArgOpener); + return parseTableGenDAGArgAndList(Tok); + } + // SimpleValue 9: Bang operator + if (Tok->is(TT_TableGenBangOperator)) { + if (CurrentToken && CurrentToken->is(tok::less)) { + CurrentToken->setType(TT_TemplateOpener); + skipToNextNonComment(); + if (!parseAngle()) + return false; + } + if (!CurrentToken || CurrentToken->isNot(tok::l_paren)) + return false; + skipToNextNonComment(); + // FIXME: Hack using inheritance to child context + Contexts.back().IsTableGenBangOpe = true; + bool Result = parseParens(); + Contexts.back().IsTableGenBangOpe = false; + return Result; + } + // SimpleValue 9: Cond operator + if (Tok->is(TT_TableGenCondOperator)) { + Tok = CurrentToken; + skipToNextNonComment(); + if (!Tok || Tok->isNot(tok::l_paren)) + return false; + bool Result = parseParens(); + return Result; + } + // We have to check identifier at the last because the kind of bang/cond + // operators are also identifier. + // SimpleValue 7: Identifiers + if (Tok->is(tok::identifier)) { + // SimpleValue 8: Anonymous record + if (CurrentToken && CurrentToken->is(tok::less)) { + CurrentToken->setType(TT_TemplateOpener); + skipToNextNonComment(); + return parseAngle(); + } + return true; + } + + return false; + } + bool couldBeInStructArrayInitializer() const { if (Contexts.size() < 2) return false; @@ -880,6 +1132,8 @@ private: OpeningBrace.getPreviousNonComment()->isNot(Keywords.kw_apostrophe))) { Contexts.back().VerilogMayBeConcatenation = true; } + if (Style.isTableGen()) + Contexts.back().ColonIsDictLiteral = false; unsigned CommaCount = 0; while (CurrentToken) { @@ -906,7 +1160,7 @@ private: FormatToken *Previous = CurrentToken->getPreviousNonComment(); if (Previous->is(TT_JsTypeOptionalQuestion)) Previous = Previous->getPreviousNonComment(); - if ((CurrentToken->is(tok::colon) && + if ((CurrentToken->is(tok::colon) && !Style.isTableGen() && (!Contexts.back().ColonIsDictLiteral || !Style.isCpp())) || Style.isProto()) { OpeningBrace.setType(TT_DictLiteral); @@ -915,10 +1169,12 @@ private: Previous->setType(TT_SelectorName); } } - if (CurrentToken->is(tok::colon) && OpeningBrace.is(TT_Unknown)) + if (CurrentToken->is(tok::colon) && OpeningBrace.is(TT_Unknown) && + !Style.isTableGen()) { OpeningBrace.setType(TT_DictLiteral); - else if (Style.isJavaScript()) + } else if (Style.isJavaScript()) { OpeningBrace.overwriteFixedType(TT_DictLiteral); + } } if (CurrentToken->is(tok::comma)) { if (Style.isJavaScript()) @@ -989,6 +1245,9 @@ private: // operators. if (Tok->is(TT_VerilogTableItem)) return true; + // Multi-line string itself is a single annotated token. + if (Tok->is(TT_TableGenMultiLineString)) + return true; switch (Tok->Tok.getKind()) { case tok::plus: case tok::minus: @@ -1119,6 +1378,10 @@ private: Tok->setType(TT_ObjCMethodExpr); } else if (Contexts.back().ContextKind == tok::l_paren && !Line.InPragmaDirective) { + if (Style.isTableGen() && Contexts.back().IsTableGenDAGArg) { + Tok->setType(TT_TableGenDAGArgListColon); + break; + } Tok->setType(TT_InlineASMColon); } break; @@ -1130,6 +1393,14 @@ private: Tok->setType(TT_JsTypeOperator); break; case tok::kw_if: + if (Style.isTableGen()) { + // In TableGen it has the form 'if' 'then'. + if (!parseTableGenValue()) + return false; + if (CurrentToken && CurrentToken->is(Keywords.kw_then)) + next(); // skip then + break; + } if (CurrentToken && CurrentToken->isOneOf(tok::kw_constexpr, tok::identifier)) { next(); @@ -1235,6 +1506,8 @@ private: } break; case tok::l_square: + if (Style.isTableGen()) + Tok->setType(TT_TableGenListOpener); if (!parseSquare()) return false; break; @@ -1264,6 +1537,8 @@ private: if (Previous && Previous->getType() != TT_DictLiteral) Previous->setType(TT_SelectorName); } + if (Style.isTableGen()) + Tok->setType(TT_TemplateOpener); } else { Tok->setType(TT_BinaryOperator); NonTemplateLess.insert(Tok); @@ -1423,11 +1698,28 @@ private: if (!Tok->getPreviousNonComment()) Line.IsContinuation = true; } + if (Style.isTableGen()) { + if (Tok->is(Keywords.kw_assert)) { + if (!parseTableGenValue()) + return false; + } else if (Tok->isOneOf(Keywords.kw_def, Keywords.kw_defm) && + (!Tok->Next || + !Tok->Next->isOneOf(tok::colon, tok::l_brace))) { + // The case NameValue appears. + if (!parseTableGenValue(true)) + return false; + } + } break; case tok::arrow: if (Tok->Previous && Tok->Previous->is(tok::kw_noexcept)) Tok->setType(TT_TrailingReturnArrow); break; + case tok::equal: + // In TableGen, there must be a value after "="; + if (Style.isTableGen() && !parseTableGenValue()) + return false; + break; default: break; } @@ -1757,6 +2049,9 @@ private: // Whether the braces may mean concatenation instead of structure or array // literal. bool VerilogMayBeConcatenation = false; + bool IsTableGenDAGArg = false; + bool IsTableGenBangOpe = false; + bool IsTableGenCondOpe = false; enum { Unknown, // Like the part after `:` in a constructor. @@ -2061,6 +2356,9 @@ private: // In JavaScript, `interface X { foo?(): bar; }` is an optional method // on the interface, not a ternary expression. Current.setType(TT_JsTypeOptionalQuestion); + } else if (Style.isTableGen()) { + // In TableGen, '?' is just an identifier like token. + Current.setType(TT_Unknown); } else { Current.setType(TT_ConditionalExpr); } @@ -2239,6 +2537,9 @@ private: // keywords such as let and def* defines names. if (Keywords.isTableGenDefinition(*PreviousNotConst)) return true; + // Otherwise C++ style declarations is available only inside the brace. + if (Contexts.back().ContextKind != tok::l_brace) + return false; } bool IsPPKeyword = PreviousNotConst->is(tok::identifier) && @@ -5184,8 +5485,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, // concept ... if (Right.is(tok::kw_concept)) return Style.BreakBeforeConceptDeclarations == FormatStyle::BBCDS_Always; - return Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Yes || - (Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Leave && + return Style.BreakTemplateDeclarations == FormatStyle::BTDS_Yes || + (Style.BreakTemplateDeclarations == FormatStyle::BTDS_Leave && Right.NewlinesBefore > 0); } if (Left.ClosesRequiresClause && Right.isNot(tok::semi)) { @@ -5620,7 +5921,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, if (Right.is(TT_RequiresClause)) return true; if (Left.ClosesTemplateDeclaration) { - return Style.AlwaysBreakTemplateDeclarations != FormatStyle::BTDS_Leave || + return Style.BreakTemplateDeclarations != FormatStyle::BTDS_Leave || Right.NewlinesBefore > 0; } if (Left.is(TT_FunctionAnnotationRParen)) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index d4f9b3f9df524eaf4acb3916c24eebff529c779f..8f6453a25d9d4102afeaea7968133181ab49b918 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -495,12 +495,15 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) { do { NextTok = Tokens->getNextToken(); } while (NextTok->is(tok::comment)); - while (NextTok->is(tok::hash) && !Line->InMacroBody) { - NextTok = Tokens->getNextToken(); - do { + if (!Style.isTableGen()) { + // InTableGen, '#' is like binary operator. Not a preprocessor directive. + while (NextTok->is(tok::hash) && !Line->InMacroBody) { NextTok = Tokens->getNextToken(); - } while (NextTok->is(tok::comment) || - (NextTok->NewlinesBefore == 0 && NextTok->isNot(tok::eof))); + do { + NextTok = Tokens->getNextToken(); + } while (NextTok->is(tok::comment) || + (NextTok->NewlinesBefore == 0 && NextTok->isNot(tok::eof))); + } } switch (Tok->Tok.getKind()) { @@ -2515,7 +2518,7 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { parseChildBlock(); break; case tok::r_paren: - if (!MightBeStmtExpr && + if (!MightBeStmtExpr && !Line->InMacroBody && Style.RemoveParentheses > FormatStyle::RPS_Leave) { const auto *Prev = LeftParen->Previous; const auto *Next = Tokens->peekNextToken(); diff --git a/clang/lib/Frontend/DependencyFile.cpp b/clang/lib/Frontend/DependencyFile.cpp index 19abcac2befbdd12d45ef1d7dcd54c8fa5e5a25a..369816e89e1d6cc21c9b3f1768887a32441e22a3 100644 --- a/clang/lib/Frontend/DependencyFile.cpp +++ b/clang/lib/Frontend/DependencyFile.cpp @@ -66,7 +66,8 @@ struct DepCollectorPPCallbacks : public PPCallbacks { StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override { if (!File) DepCollector.maybeAddDependency(FileName, /*FromModule*/ false, diff --git a/clang/lib/Frontend/DependencyGraph.cpp b/clang/lib/Frontend/DependencyGraph.cpp index b471471f3528a7ff770bbf6f6f38c684d8e45e5f..20e5f233e224e2ca98b1c364771cf99ee747af61 100644 --- a/clang/lib/Frontend/DependencyGraph.cpp +++ b/clang/lib/Frontend/DependencyGraph.cpp @@ -49,7 +49,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override; void EndOfMainFile() override { @@ -68,8 +69,8 @@ void clang::AttachDependencyGraphGen(Preprocessor &PP, StringRef OutputFile, void DependencyGraphCallback::InclusionDirective( SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, - StringRef SearchPath, StringRef RelativePath, const Module *Imported, - SrcMgr::CharacteristicKind FileType) { + StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) { if (!File) return; diff --git a/clang/lib/Frontend/ModuleDependencyCollector.cpp b/clang/lib/Frontend/ModuleDependencyCollector.cpp index 939e611e548998fe6a512464da2aedcb818229ad..b88cb60ebdd2a563923283aee7971d487794402f 100644 --- a/clang/lib/Frontend/ModuleDependencyCollector.cpp +++ b/clang/lib/Frontend/ModuleDependencyCollector.cpp @@ -55,7 +55,8 @@ struct ModuleDependencyPPCallbacks : public PPCallbacks { StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override { if (!File) return; diff --git a/clang/lib/Frontend/PrecompiledPreamble.cpp b/clang/lib/Frontend/PrecompiledPreamble.cpp index 62373b23b82efbd4f2c5cb27134421c34bd75e00..9b0ef30a14121bc67dddb2fe91795a7aac42648f 100644 --- a/clang/lib/Frontend/PrecompiledPreamble.cpp +++ b/clang/lib/Frontend/PrecompiledPreamble.cpp @@ -98,7 +98,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override { // File is std::nullopt if it wasn't found. // (We have some false negatives if PP recovered e.g. -> "foo") diff --git a/clang/lib/Frontend/PrintPreprocessedOutput.cpp b/clang/lib/Frontend/PrintPreprocessedOutput.cpp index 7f5f6690682300e8ed8ee5223c125bbea93ef4dd..a26d2c3ab8582b9babafb078c01c64ed241b4705 100644 --- a/clang/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/clang/lib/Frontend/PrintPreprocessedOutput.cpp @@ -153,7 +153,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override; void Ident(SourceLocation Loc, StringRef str) override; void PragmaMessage(SourceLocation Loc, StringRef Namespace, @@ -401,8 +402,8 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, void PrintPPOutputPPCallbacks::InclusionDirective( SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, - StringRef SearchPath, StringRef RelativePath, const Module *Imported, - SrcMgr::CharacteristicKind FileType) { + StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) { // In -dI mode, dump #include directives prior to dumping their content or // interpretation. Similar for -fkeep-system-includes. if (DumpIncludeDirectives || (KeepSystemIncludes && isSystem(FileType))) { @@ -418,14 +419,14 @@ void PrintPPOutputPPCallbacks::InclusionDirective( } // When preprocessing, turn implicit imports into module import pragmas. - if (Imported) { + if (ModuleImported) { switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { case tok::pp_include: case tok::pp_import: case tok::pp_include_next: MoveToLine(HashLoc, /*RequireStartOfLine=*/true); *OS << "#pragma clang module import " - << Imported->getFullModuleName(true) + << SuggestedModule->getFullModuleName(true) << " /* clang -E: implicit import for " << "#" << PP.getSpelling(IncludeTok) << " " << (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"') diff --git a/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp b/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp index b6b37461089e4860e5f46cf8ec2b78121f08a96d..1462058003b3d457127b9dd377495776d83be040 100644 --- a/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp +++ b/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp @@ -75,7 +75,8 @@ private: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override; void If(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind ConditionValue) override; @@ -189,9 +190,10 @@ void InclusionRewriter::InclusionDirective( StringRef /*FileName*/, bool /*IsAngled*/, CharSourceRange /*FilenameRange*/, OptionalFileEntryRef /*File*/, StringRef /*SearchPath*/, StringRef /*RelativePath*/, - const Module *Imported, SrcMgr::CharacteristicKind FileType) { - if (Imported) { - auto P = ModuleIncludes.insert(std::make_pair(HashLoc, Imported)); + const Module *SuggestedModule, bool ModuleImported, + SrcMgr::CharacteristicKind FileType) { + if (ModuleImported) { + auto P = ModuleIncludes.insert(std::make_pair(HashLoc, SuggestedModule)); (void)P; assert(P.second && "Unexpected revisitation of the same include directive"); } else diff --git a/clang/lib/Headers/ia32intrin.h b/clang/lib/Headers/ia32intrin.h index 1b979770e19623389e4b7ec0a2c8ed07456ad2e3..8e65f232a0def8b0b7b80f9bdb5d80c68beded6d 100644 --- a/clang/lib/Headers/ia32intrin.h +++ b/clang/lib/Headers/ia32intrin.h @@ -26,8 +26,8 @@ #define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS #endif -/// Find the first set bit starting from the lsb. Result is undefined if -/// input is 0. +/// Finds the first set bit starting from the least significant bit. The result +/// is undefined if the input is 0. /// /// \headerfile /// @@ -43,8 +43,8 @@ __bsfd(int __A) { return __builtin_ctz((unsigned int)__A); } -/// Find the first set bit starting from the msb. Result is undefined if -/// input is 0. +/// Finds the first set bit starting from the most significant bit. The result +/// is undefined if the input is 0. /// /// \headerfile /// @@ -90,8 +90,8 @@ _bswap(int __A) { return (int)__builtin_bswap32((unsigned int)__A); } -/// Find the first set bit starting from the lsb. Result is undefined if -/// input is 0. +/// Finds the first set bit starting from the least significant bit. The result +/// is undefined if the input is 0. /// /// \headerfile /// @@ -108,8 +108,8 @@ _bswap(int __A) { /// \see __bsfd #define _bit_scan_forward(A) __bsfd((A)) -/// Find the first set bit starting from the msb. Result is undefined if -/// input is 0. +/// Finds the first set bit starting from the most significant bit. The result +/// is undefined if the input is 0. /// /// \headerfile /// @@ -127,8 +127,8 @@ _bswap(int __A) { #define _bit_scan_reverse(A) __bsrd((A)) #ifdef __x86_64__ -/// Find the first set bit starting from the lsb. Result is undefined if -/// input is 0. +/// Finds the first set bit starting from the least significant bit. The result +/// is undefined if the input is 0. /// /// \headerfile /// @@ -143,8 +143,8 @@ __bsfq(long long __A) { return (long long)__builtin_ctzll((unsigned long long)__A); } -/// Find the first set bit starting from the msb. Result is undefined if -/// input is 0. +/// Finds the first set bit starting from the most significant bit. The result +/// is undefined if input is 0. /// /// \headerfile /// @@ -159,7 +159,7 @@ __bsrq(long long __A) { return 63 - __builtin_clzll((unsigned long long)__A); } -/// Swaps the bytes in the input. Converting little endian to big endian or +/// Swaps the bytes in the input, converting little endian to big endian or /// vice versa. /// /// \headerfile @@ -175,7 +175,7 @@ __bswapq(long long __A) { return (long long)__builtin_bswap64((unsigned long long)__A); } -/// Swaps the bytes in the input. Converting little endian to big endian or +/// Swaps the bytes in the input, converting little endian to big endian or /// vice versa. /// /// \headerfile @@ -198,7 +198,7 @@ __bswapq(long long __A) { /// \headerfile /// /// This intrinsic corresponds to the \c POPCNT instruction or a -/// a sequence of arithmetic and logic ops to calculate it. +/// sequence of arithmetic and logic operations to calculate it. /// /// \param __A /// An unsigned 32-bit integer operand. @@ -220,7 +220,7 @@ __popcntd(unsigned int __A) /// \endcode /// /// This intrinsic corresponds to the \c POPCNT instruction or a -/// a sequence of arithmetic and logic ops to calculate it. +/// sequence of arithmetic and logic operations to calculate it. /// /// \param A /// An unsigned 32-bit integer operand. @@ -235,7 +235,7 @@ __popcntd(unsigned int __A) /// \headerfile /// /// This intrinsic corresponds to the \c POPCNT instruction or a -/// a sequence of arithmetic and logic ops to calculate it. +/// sequence of arithmetic and logic operations to calculate it. /// /// \param __A /// An unsigned 64-bit integer operand. @@ -257,7 +257,7 @@ __popcntq(unsigned long long __A) /// \endcode /// /// This intrinsic corresponds to the \c POPCNT instruction or a -/// a sequence of arithmetic and logic ops to calculate it. +/// sequence of arithmetic and logic operations to calculate it. /// /// \param A /// An unsigned 64-bit integer operand. @@ -268,7 +268,7 @@ __popcntq(unsigned long long __A) #endif /* __x86_64__ */ #ifdef __x86_64__ -/// Returns the program status and control \c RFLAGS register with the \c VM +/// Returns the program status-and-control \c RFLAGS register with the \c VM /// and \c RF flags cleared. /// /// \headerfile @@ -282,7 +282,7 @@ __readeflags(void) return __builtin_ia32_readeflags_u64(); } -/// Writes the specified value to the program status and control \c RFLAGS +/// Writes the specified value to the program status-and-control \c RFLAGS /// register. Reserved bits are not affected. /// /// \headerfile @@ -298,7 +298,7 @@ __writeeflags(unsigned long long __f) } #else /* !__x86_64__ */ -/// Returns the program status and control \c EFLAGS register with the \c VM +/// Returns the program status-and-control \c EFLAGS register with the \c VM /// and \c RF flags cleared. /// /// \headerfile @@ -312,7 +312,7 @@ __readeflags(void) return __builtin_ia32_readeflags_u32(); } -/// Writes the specified value to the program status and control \c EFLAGS +/// Writes the specified value to the program status-and-control \c EFLAGS /// register. Reserved bits are not affected. /// /// \headerfile @@ -328,7 +328,7 @@ __writeeflags(unsigned int __f) } #endif /* !__x86_64__ */ -/// Cast a 32-bit float value to a 32-bit unsigned integer value. +/// Casts a 32-bit float value to a 32-bit unsigned integer value. /// /// \headerfile /// @@ -337,13 +337,13 @@ __writeeflags(unsigned int __f) /// /// \param __A /// A 32-bit float value. -/// \returns a 32-bit unsigned integer containing the converted value. +/// \returns A 32-bit unsigned integer containing the converted value. static __inline__ unsigned int __DEFAULT_FN_ATTRS_CAST _castf32_u32(float __A) { return __builtin_bit_cast(unsigned int, __A); } -/// Cast a 64-bit float value to a 64-bit unsigned integer value. +/// Casts a 64-bit float value to a 64-bit unsigned integer value. /// /// \headerfile /// @@ -352,13 +352,13 @@ _castf32_u32(float __A) { /// /// \param __A /// A 64-bit float value. -/// \returns a 64-bit unsigned integer containing the converted value. +/// \returns A 64-bit unsigned integer containing the converted value. static __inline__ unsigned long long __DEFAULT_FN_ATTRS_CAST _castf64_u64(double __A) { return __builtin_bit_cast(unsigned long long, __A); } -/// Cast a 32-bit unsigned integer value to a 32-bit float value. +/// Casts a 32-bit unsigned integer value to a 32-bit float value. /// /// \headerfile /// @@ -367,13 +367,13 @@ _castf64_u64(double __A) { /// /// \param __A /// A 32-bit unsigned integer value. -/// \returns a 32-bit float value containing the converted value. +/// \returns A 32-bit float value containing the converted value. static __inline__ float __DEFAULT_FN_ATTRS_CAST _castu32_f32(unsigned int __A) { return __builtin_bit_cast(float, __A); } -/// Cast a 64-bit unsigned integer value to a 64-bit float value. +/// Casts a 64-bit unsigned integer value to a 64-bit float value. /// /// \headerfile /// @@ -382,7 +382,7 @@ _castu32_f32(unsigned int __A) { /// /// \param __A /// A 64-bit unsigned integer value. -/// \returns a 64-bit float value containing the converted value. +/// \returns A 64-bit float value containing the converted value. static __inline__ double __DEFAULT_FN_ATTRS_CAST _castu64_f64(unsigned long long __A) { return __builtin_bit_cast(double, __A); @@ -470,7 +470,7 @@ __crc32q(unsigned long long __C, unsigned long long __D) } #endif /* __x86_64__ */ -/// Reads the specified performance monitoring counter. Refer to your +/// Reads the specified performance-monitoring counter. Refer to your /// processor's documentation to determine which performance counters are /// supported. /// @@ -487,7 +487,7 @@ __rdpmc(int __A) { return __builtin_ia32_rdpmc(__A); } -/// Reads the processor's time stamp counter and the \c IA32_TSC_AUX MSR +/// Reads the processor's time-stamp counter and the \c IA32_TSC_AUX MSR /// \c (0xc0000103). /// /// \headerfile @@ -495,14 +495,14 @@ __rdpmc(int __A) { /// This intrinsic corresponds to the \c RDTSCP instruction. /// /// \param __A -/// Address of where to store the 32-bit \c IA32_TSC_AUX value. -/// \returns The 64-bit value of the time stamp counter. +/// The address of where to store the 32-bit \c IA32_TSC_AUX value. +/// \returns The 64-bit value of the time-stamp counter. static __inline__ unsigned long long __DEFAULT_FN_ATTRS __rdtscp(unsigned int *__A) { return __builtin_ia32_rdtscp(__A); } -/// Reads the processor's time stamp counter. +/// Reads the processor's time-stamp counter. /// /// \headerfile /// @@ -512,7 +512,7 @@ __rdtscp(unsigned int *__A) { /// /// This intrinsic corresponds to the \c RDTSC instruction. /// -/// \returns The 64-bit value of the time stamp counter. +/// \returns The 64-bit value of the time-stamp counter. #define _rdtsc() __rdtsc() /// Reads the specified performance monitoring counter. Refer to your diff --git a/clang/lib/Headers/stdatomic.h b/clang/lib/Headers/stdatomic.h index 521c473dd169ab8367410719039e3b487486fe21..9c103d98af8c5694cdeb122733e4fdb7827910a6 100644 --- a/clang/lib/Headers/stdatomic.h +++ b/clang/lib/Headers/stdatomic.h @@ -16,7 +16,7 @@ * Exclude the MSVC path as well as the MSVC header as of the 14.31.30818 * explicitly disallows `stdatomic.h` in the C mode via an `#error`. Fallback * to the clang resource header until that is fully supported. The - * `stdatomic.h` header requires C++ 23 or newer. + * `stdatomic.h` header requires C++23 or newer. */ #if __STDC_HOSTED__ && \ __has_include_next() && \ diff --git a/clang/lib/Lex/DependencyDirectivesScanner.cpp b/clang/lib/Lex/DependencyDirectivesScanner.cpp index 980f865cf24c97e75837b5c0b348da06f6203a7d..0971daa1f36663f0bb17177e1b65f84dfddfc786 100644 --- a/clang/lib/Lex/DependencyDirectivesScanner.cpp +++ b/clang/lib/Lex/DependencyDirectivesScanner.cpp @@ -369,7 +369,7 @@ static void skipBlockComment(const char *&First, const char *const End) { } } -/// \returns True if the current single quotation mark character is a C++ 14 +/// \returns True if the current single quotation mark character is a C++14 /// digit separator. static bool isQuoteCppDigitSeparator(const char *const Start, const char *const Cur, diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index a980f4bcbae1245f4197994b4f8152f330e77080..0b22139ebe81deed4c4948b7d82568164c46a2c9 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -2253,26 +2253,27 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // FIXME: We do not have a good way to disambiguate C++ clang modules from // C++ standard modules (other than use/non-use of Header Units). - Module *SM = SuggestedModule.getModule(); - bool MaybeTranslateInclude = - Action == Enter && File && SM && !SM->isForBuilding(getLangOpts()); + Module *ModuleToImport = SuggestedModule.getModule(); + + bool MaybeTranslateInclude = Action == Enter && File && ModuleToImport && + !ModuleToImport->isForBuilding(getLangOpts()); // Maybe a usable Header Unit bool UsableHeaderUnit = false; - if (getLangOpts().CPlusPlusModules && SM && SM->isHeaderUnit()) { + if (getLangOpts().CPlusPlusModules && ModuleToImport && + ModuleToImport->isHeaderUnit()) { if (TrackGMFState.inGMF() || IsImportDecl) UsableHeaderUnit = true; else if (!IsImportDecl) { // This is a Header Unit that we do not include-translate - SuggestedModule = ModuleMap::KnownHeader(); - SM = nullptr; + ModuleToImport = nullptr; } } // Maybe a usable clang header module. bool UsableClangHeaderModule = - (getLangOpts().CPlusPlusModules || getLangOpts().Modules) && SM && - !SM->isHeaderUnit(); + (getLangOpts().CPlusPlusModules || getLangOpts().Modules) && + ModuleToImport && !ModuleToImport->isHeaderUnit(); // Determine whether we should try to import the module for this #include, if // there is one. Don't do so if precompiled module support is disabled or we @@ -2282,12 +2283,11 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // unavailable, diagnose the situation and bail out. // FIXME: Remove this; loadModule does the same check (but produces // slightly worse diagnostics). - if (checkModuleIsAvailable(getLangOpts(), getTargetInfo(), - *SuggestedModule.getModule(), + if (checkModuleIsAvailable(getLangOpts(), getTargetInfo(), *ModuleToImport, getDiagnostics())) { Diag(FilenameTok.getLocation(), diag::note_implicit_top_level_module_import_here) - << SuggestedModule.getModule()->getTopLevelModuleName(); + << ModuleToImport->getTopLevelModuleName(); return {ImportAction::None}; } @@ -2295,7 +2295,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // FIXME: Should we have a second loadModule() overload to avoid this // extra lookup step? SmallVector, 2> Path; - for (Module *Mod = SM; Mod; Mod = Mod->Parent) + for (Module *Mod = ModuleToImport; Mod; Mod = Mod->Parent) Path.push_back(std::make_pair(getIdentifierInfo(Mod->Name), FilenameTok.getLocation())); std::reverse(Path.begin(), Path.end()); @@ -2306,12 +2306,12 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // Load the module to import its macros. We'll make the declarations // visible when the parser gets here. - // FIXME: Pass SuggestedModule in here rather than converting it to a path + // FIXME: Pass ModuleToImport in here rather than converting it to a path // and making the module loader convert it back again. ModuleLoadResult Imported = TheModuleLoader.loadModule( IncludeTok.getLocation(), Path, Module::Hidden, /*IsInclusionDirective=*/true); - assert((Imported == nullptr || Imported == SuggestedModule.getModule()) && + assert((Imported == nullptr || Imported == ModuleToImport) && "the imported module is different than the suggested one"); if (Imported) { @@ -2323,8 +2323,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // was in the directory of an umbrella header, for instance), but no // actual module containing it exists (because the umbrella header is // incomplete). Treat this as a textual inclusion. - SuggestedModule = ModuleMap::KnownHeader(); - SM = nullptr; + ModuleToImport = nullptr; } else if (Imported.isConfigMismatch()) { // On a configuration mismatch, enter the header textually. We still know // that it's part of the corresponding module. @@ -2365,7 +2364,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // this file will have no effect. if (Action == Enter && File && !HeaderInfo.ShouldEnterIncludeFile(*this, *File, EnterOnce, - getLangOpts().Modules, SM, + getLangOpts().Modules, ModuleToImport, IsFirstIncludeOfFile)) { // C++ standard modules: // If we are not in the GMF, then we textually include only @@ -2380,7 +2379,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( if (UsableHeaderUnit && !getLangOpts().CompilingPCH) Action = TrackGMFState.inGMF() ? Import : Skip; else - Action = (SuggestedModule && !getLangOpts().CompilingPCH) ? Import : Skip; + Action = (ModuleToImport && !getLangOpts().CompilingPCH) ? Import : Skip; } // Check for circular inclusion of the main file. @@ -2400,8 +2399,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // FIXME: Use a different callback for a pp-import? Callbacks->InclusionDirective(HashLoc, IncludeTok, LookupFilename, isAngled, FilenameRange, File, SearchPath, RelativePath, - Action == Import ? SuggestedModule.getModule() - : nullptr, + SuggestedModule.getModule(), Action == Import, FileCharacter); if (Action == Skip && File) Callbacks->FileSkipped(*File, FilenameTok, FileCharacter); @@ -2412,7 +2410,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // If this is a C++20 pp-import declaration, diagnose if we didn't find any // module corresponding to the named header. - if (IsImportDecl && !SuggestedModule) { + if (IsImportDecl && !ModuleToImport) { Diag(FilenameTok, diag::err_header_import_not_header_unit) << OriginalFilename << File->getName(); return {ImportAction::None}; @@ -2517,8 +2515,8 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( switch (Action) { case Skip: // If we don't need to enter the file, stop now. - if (SM) - return {ImportAction::SkippedModuleImport, SM}; + if (ModuleToImport) + return {ImportAction::SkippedModuleImport, ModuleToImport}; return {ImportAction::None}; case IncludeLimitReached: @@ -2528,15 +2526,15 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( case Import: { // If this is a module import, make it visible if needed. - assert(SM && "no module to import"); + assert(ModuleToImport && "no module to import"); - makeModuleVisible(SM, EndLoc); + makeModuleVisible(ModuleToImport, EndLoc); if (IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp___include_macros) return {ImportAction::None}; - return {ImportAction::ModuleImport, SM}; + return {ImportAction::ModuleImport, ModuleToImport}; } case Enter: @@ -2573,13 +2571,14 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // Determine if we're switching to building a new submodule, and which one. // This does not apply for C++20 modules header units. - if (SM && !SM->isHeaderUnit()) { - if (SM->getTopLevelModule()->ShadowingModule) { + if (ModuleToImport && !ModuleToImport->isHeaderUnit()) { + if (ModuleToImport->getTopLevelModule()->ShadowingModule) { // We are building a submodule that belongs to a shadowed module. This // means we find header files in the shadowed module. - Diag(SM->DefinitionLoc, diag::err_module_build_shadowed_submodule) - << SM->getFullModuleName(); - Diag(SM->getTopLevelModule()->ShadowingModule->DefinitionLoc, + Diag(ModuleToImport->DefinitionLoc, + diag::err_module_build_shadowed_submodule) + << ModuleToImport->getFullModuleName(); + Diag(ModuleToImport->getTopLevelModule()->ShadowingModule->DefinitionLoc, diag::note_previous_definition); return {ImportAction::None}; } @@ -2591,21 +2590,22 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // that behaves the same as the header would behave in a compilation using // that PCH, which means we should enter the submodule. We need to teach // the AST serialization layer to deal with the resulting AST. - if (getLangOpts().CompilingPCH && SM->isForBuilding(getLangOpts())) + if (getLangOpts().CompilingPCH && + ModuleToImport->isForBuilding(getLangOpts())) return {ImportAction::None}; assert(!CurLexerSubmodule && "should not have marked this as a module yet"); - CurLexerSubmodule = SM; + CurLexerSubmodule = ModuleToImport; // Let the macro handling code know that any future macros are within // the new submodule. - EnterSubmodule(SM, EndLoc, /*ForPragma*/ false); + EnterSubmodule(ModuleToImport, EndLoc, /*ForPragma*/ false); // Let the parser know that any future declarations are within the new // submodule. // FIXME: There's no point doing this if we're handling a #__include_macros // directive. - return {ImportAction::ModuleBegin, SM}; + return {ImportAction::ModuleBegin, ModuleToImport}; } assert(!IsImportDecl && "failed to diagnose missing module for import decl"); diff --git a/clang/lib/Lex/PreprocessingRecord.cpp b/clang/lib/Lex/PreprocessingRecord.cpp index aab6a2bed89d9545c9a763e4f21f37111e13f1ad..be5aac7ef31b886a1f8fb7a47ae91e1dc68056af 100644 --- a/clang/lib/Lex/PreprocessingRecord.cpp +++ b/clang/lib/Lex/PreprocessingRecord.cpp @@ -472,8 +472,8 @@ void PreprocessingRecord::MacroUndefined(const Token &Id, void PreprocessingRecord::InclusionDirective( SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, - StringRef SearchPath, StringRef RelativePath, const Module *Imported, - SrcMgr::CharacteristicKind FileType) { + StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) { InclusionDirective::InclusionKind Kind = InclusionDirective::Include; switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { @@ -506,10 +506,9 @@ void PreprocessingRecord::InclusionDirective( EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects // a token range. } - clang::InclusionDirective *ID = - new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, - (bool)Imported, File, - SourceRange(HashLoc, EndLoc)); + clang::InclusionDirective *ID = new (*this) clang::InclusionDirective( + *this, Kind, FileName, !IsAngled, ModuleImported, File, + SourceRange(HashLoc, EndLoc)); addPreprocessedEntity(ID); } diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index 1fee9f82b3e6a3872869e70d326a31ec63b26e04..e099d077198d099667defd50de16e7baaf85f9c1 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -54,7 +54,7 @@ OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) { .Case("declare", OpenACCDirectiveKind::Declare) .Case("init", OpenACCDirectiveKind::Init) .Case("shutdown", OpenACCDirectiveKind::Shutdown) - .Case("set", OpenACCDirectiveKind::Shutdown) + .Case("set", OpenACCDirectiveKind::Set) .Case("update", OpenACCDirectiveKind::Update) .Case("wait", OpenACCDirectiveKind::Wait) .Default(OpenACCDirectiveKind::Invalid); diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 78b9f324e1390616bdcced06ada46ed36b783b72..8239ba49429d3c5c6fede316a11034c24783cf49 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2297,7 +2297,8 @@ public: void handleUnsafeVariableGroup(const VarDecl *Variable, const VariableGroupsManager &VarGrpMgr, - FixItList &&Fixes, const Decl *D) override { + FixItList &&Fixes, const Decl *D, + const FixitStrategy &VarTargetTypes) override { assert(!SuggestSuggestions && "Unsafe buffer usage fixits displayed without suggestions!"); S.Diag(Variable->getLocation(), diag::warn_unsafe_buffer_variable) @@ -2312,7 +2313,18 @@ public: // NOT explain how the variables are grouped as the reason is non-trivial // and irrelavant to users' experience: const auto VarGroupForVD = VarGrpMgr.getGroupOfVar(Variable, &BriefMsg); - unsigned FixItStrategy = 0; // For now we only have 'std::span' strategy + unsigned FixItStrategy = 0; + switch (VarTargetTypes.lookup(Variable)) { + case clang::FixitStrategy::Kind::Span: + FixItStrategy = 0; + break; + case clang::FixitStrategy::Kind::Array: + FixItStrategy = 1; + break; + default: + assert(false && "We support only std::span and std::array"); + }; + const auto &FD = S.Diag(Variable->getLocation(), BriefMsg ? diag::note_unsafe_buffer_variable_fixit_together diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 2d4e6d1d058cd7df30708b75460ecb187d3e511e..cfb653e665ea03dcd422634b8a54f14a95098b7f 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1393,7 +1393,8 @@ void Sema::ActOnEndOfTranslationUnit() { Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl) << /*function=*/0 << DiagD << DiagRange; } - } else { + } else if (!FD->isTargetMultiVersion() || + FD->isTargetMultiVersionDefault()) { if (FD->getDescribedFunctionTemplate()) Diag(DiagD->getLocation(), diag::warn_unused_template) << /*function=*/0 << DiagD << DiagRange; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index b071a02ca3713f4422eb5cc78844f581f32ce9d1..afe2673479e40adebc13a65fc4dcc1c2748bd0ee 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -7162,13 +7162,11 @@ static bool CheckNonNullExpr(Sema &S, const Expr *Expr) { // As a special case, transparent unions initialized with zero are // considered null for the purposes of the nonnull attribute. - if (const RecordType *UT = Expr->getType()->getAsUnionType()) { - if (UT->getDecl()->hasAttr()) - if (const CompoundLiteralExpr *CLE = - dyn_cast(Expr)) - if (const InitListExpr *ILE = - dyn_cast(CLE->getInitializer())) - Expr = ILE->getInit(0); + if (const RecordType *UT = Expr->getType()->getAsUnionType(); + UT && UT->getDecl()->hasAttr()) { + if (const auto *CLE = dyn_cast(Expr)) + if (const auto *ILE = dyn_cast(CLE->getInitializer())) + Expr = ILE->getInit(0); } bool Result; @@ -16129,10 +16127,10 @@ static void CheckConditionalOperator(Sema &S, AbstractConditionalOperator *E, /// Check conversion of given expression to boolean. /// Input argument E is a logical expression. static void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) { - // While C23 does have bool as a keyword, we still need to run the bool-like - // conversion checks as bools are still not used as the return type from - // "boolean" operators or as the input type for conditional operators. - if (S.getLangOpts().Bool && !S.getLangOpts().C23) + // Run the bool-like conversion checks only for C since there bools are + // still not used as the return type from "boolean" operators or as the input + // type for conditional operators. + if (S.getLangOpts().CPlusPlus) return; if (E->IgnoreParenImpCasts()->getType()->isAtomicType()) return; @@ -16652,6 +16650,7 @@ class SequenceChecker : public ConstEvaluatedExprVisitor { struct Value { explicit Value(unsigned Parent) : Parent(Parent), Merged(false) {} unsigned Parent : 31; + LLVM_PREFERRED_TYPE(bool) unsigned Merged : 1; }; SmallVector Values; @@ -17183,7 +17182,7 @@ public: // evaluates to true. bool EvalResult = false; bool EvalOK = Eval.evaluate(BO->getLHS(), EvalResult); - bool ShouldVisitRHS = !EvalOK || (EvalOK && !EvalResult); + bool ShouldVisitRHS = !EvalOK || !EvalResult; if (ShouldVisitRHS) { Region = RHSRegion; Visit(BO->getRHS()); @@ -17215,7 +17214,7 @@ public: // [...] the second operand is not evaluated if the first operand is false. bool EvalResult = false; bool EvalOK = Eval.evaluate(BO->getLHS(), EvalResult); - bool ShouldVisitRHS = !EvalOK || (EvalOK && EvalResult); + bool ShouldVisitRHS = !EvalOK || EvalResult; if (ShouldVisitRHS) { Region = RHSRegion; Visit(BO->getRHS()); @@ -17266,8 +17265,8 @@ public: // evaluated. [...] bool EvalResult = false; bool EvalOK = Eval.evaluate(CO->getCond(), EvalResult); - bool ShouldVisitTrueExpr = !EvalOK || (EvalOK && EvalResult); - bool ShouldVisitFalseExpr = !EvalOK || (EvalOK && !EvalResult); + bool ShouldVisitTrueExpr = !EvalOK || EvalResult; + bool ShouldVisitFalseExpr = !EvalOK || !EvalResult; if (ShouldVisitTrueExpr) { Region = TrueRegion; Visit(CO->getTrueExpr()); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 18a5d93ab8e8c639f8988032733892749faaf483..be23c0fffe0576aa34f53c1038c2740ab0ad94a6 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8357,28 +8357,40 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, unsigned WarningDiag = diag::warn_decl_shadow; SourceLocation CaptureLoc; - if (isa(D) && isa(ShadowedDecl) && NewDC && - isa(NewDC)) { + if (isa(D) && NewDC && isa(NewDC)) { if (const auto *RD = dyn_cast(NewDC->getParent())) { if (RD->isLambda() && OldDC->Encloses(NewDC->getLexicalParent())) { - if (RD->getLambdaCaptureDefault() == LCD_None) { - // Try to avoid warnings for lambdas with an explicit capture list. + if (const auto *VD = dyn_cast(ShadowedDecl)) { const auto *LSI = cast(getCurFunction()); - // Warn only when the lambda captures the shadowed decl explicitly. - CaptureLoc = getCaptureLocation(LSI, cast(ShadowedDecl)); - if (CaptureLoc.isInvalid()) - WarningDiag = diag::warn_decl_shadow_uncaptured_local; - } else { - // Remember that this was shadowed so we can avoid the warning if the - // shadowed decl isn't captured and the warning settings allow it. + if (RD->getLambdaCaptureDefault() == LCD_None) { + // Try to avoid warnings for lambdas with an explicit capture + // list. Warn only when the lambda captures the shadowed decl + // explicitly. + CaptureLoc = getCaptureLocation(LSI, VD); + if (CaptureLoc.isInvalid()) + WarningDiag = diag::warn_decl_shadow_uncaptured_local; + } else { + // Remember that this was shadowed so we can avoid the warning if + // the shadowed decl isn't captured and the warning settings allow + // it. + cast(getCurFunction()) + ->ShadowingDecls.push_back({D, VD}); + return; + } + } + if (isa(ShadowedDecl)) { + // If lambda can capture this, then emit default shadowing warning, + // Otherwise it is not really a shadowing case since field is not + // available in lambda's body. + // At this point we don't know that lambda can capture this, so + // remember that this was shadowed and delay until we know. cast(getCurFunction()) - ->ShadowingDecls.push_back( - {cast(D), cast(ShadowedDecl)}); + ->ShadowingDecls.push_back({D, ShadowedDecl}); return; } } - - if (cast(ShadowedDecl)->hasLocalStorage()) { + if (const auto *VD = dyn_cast(ShadowedDecl); + VD && VD->hasLocalStorage()) { // A variable can't shadow a local variable in an enclosing scope, if // they are separated by a non-capturing declaration context. for (DeclContext *ParentDC = NewDC; @@ -8429,19 +8441,28 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, /// when these variables are captured by the lambda. void Sema::DiagnoseShadowingLambdaDecls(const LambdaScopeInfo *LSI) { for (const auto &Shadow : LSI->ShadowingDecls) { - const VarDecl *ShadowedDecl = Shadow.ShadowedDecl; + const NamedDecl *ShadowedDecl = Shadow.ShadowedDecl; // Try to avoid the warning when the shadowed decl isn't captured. - SourceLocation CaptureLoc = getCaptureLocation(LSI, ShadowedDecl); const DeclContext *OldDC = ShadowedDecl->getDeclContext(); - Diag(Shadow.VD->getLocation(), CaptureLoc.isInvalid() - ? diag::warn_decl_shadow_uncaptured_local - : diag::warn_decl_shadow) - << Shadow.VD->getDeclName() - << computeShadowedDeclKind(ShadowedDecl, OldDC) << OldDC; - if (!CaptureLoc.isInvalid()) - Diag(CaptureLoc, diag::note_var_explicitly_captured_here) - << Shadow.VD->getDeclName() << /*explicitly*/ 0; - Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration); + if (const auto *VD = dyn_cast(ShadowedDecl)) { + SourceLocation CaptureLoc = getCaptureLocation(LSI, VD); + Diag(Shadow.VD->getLocation(), + CaptureLoc.isInvalid() ? diag::warn_decl_shadow_uncaptured_local + : diag::warn_decl_shadow) + << Shadow.VD->getDeclName() + << computeShadowedDeclKind(ShadowedDecl, OldDC) << OldDC; + if (CaptureLoc.isValid()) + Diag(CaptureLoc, diag::note_var_explicitly_captured_here) + << Shadow.VD->getDeclName() << /*explicitly*/ 0; + Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration); + } else if (isa(ShadowedDecl)) { + Diag(Shadow.VD->getLocation(), + LSI->isCXXThisCaptured() ? diag::warn_decl_shadow + : diag::warn_decl_shadow_uncaptured_local) + << Shadow.VD->getDeclName() + << computeShadowedDeclKind(ShadowedDecl, OldDC) << OldDC; + Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration); + } } } @@ -9759,7 +9780,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, SmallVector TemplateParamLists; llvm::append_range(TemplateParamLists, TemplateParamListsRef); if (TemplateParameterList *Invented = D.getInventedTemplateParameterList()) { - if (!TemplateParamLists.empty() && + if (!TemplateParamLists.empty() && !TemplateParamLists.back()->empty() && Invented->getDepth() == TemplateParamLists.back()->getDepth()) TemplateParamLists.back() = Invented; else @@ -13049,7 +13070,8 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, TemplateDeductionInfo Info(DeduceInit->getExprLoc()); TemplateDeductionResult Result = DeduceAutoType(TSI->getTypeLoc(), DeduceInit, DeducedType, Info); - if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed) { + if (Result != TemplateDeductionResult::Success && + Result != TemplateDeductionResult::AlreadyDiagnosed) { if (!IsInitCapture) DiagnoseAutoDeductionFailure(VDecl, DeduceInit); else if (isa(Init)) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index d785714c4d811e7ef9e55e30240e1470485306c1..d5526957937bbbc2dda26519197e44b3b5521e09 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3501,9 +3501,16 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { return false; } +static bool hasArmStreamingInterface(const FunctionDecl *FD) { + if (const auto *T = FD->getType()->getAs()) + if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask) + return true; + return false; +} + // Check Target Version attrs -bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, StringRef &AttrStr, - bool &isDefault) { +bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D, + StringRef &AttrStr, bool &isDefault) { enum FirstParam { Unsupported }; enum SecondParam { None }; enum ThirdParam { Target, TargetClones, TargetVersion }; @@ -3519,6 +3526,8 @@ bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, StringRef &AttrStr, return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) << Unsupported << None << CurFeature << TargetVersion; } + if (hasArmStreamingInterface(cast(D))) + return Diag(LiteralLoc, diag::err_sme_streaming_cannot_be_multiversioned); return false; } @@ -3527,7 +3536,7 @@ static void handleTargetVersionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { SourceLocation LiteralLoc; bool isDefault = false; if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) || - S.checkTargetVersionAttr(LiteralLoc, Str, isDefault)) + S.checkTargetVersionAttr(LiteralLoc, D, Str, isDefault)) return; // Do not create default only target_version attribute if (!isDefault) { @@ -3550,7 +3559,7 @@ static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) { bool Sema::checkTargetClonesAttrString( SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal, - bool &HasDefault, bool &HasCommas, bool &HasNotDefault, + Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault, SmallVectorImpl> &StringsBuffer) { enum FirstParam { Unsupported, Duplicate, Unknown }; enum SecondParam { None, CPU, Tune }; @@ -3619,6 +3628,9 @@ bool Sema::checkTargetClonesAttrString( HasNotDefault = true; } } + if (hasArmStreamingInterface(cast(D))) + return Diag(LiteralLoc, + diag::err_sme_streaming_cannot_be_multiversioned); } else { // Other targets ( currently X86 ) if (Cur.starts_with("arch=")) { @@ -3670,7 +3682,7 @@ static void handleTargetClonesAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!S.checkStringLiteralArgumentAttr(AL, I, CurStr, &LiteralLoc) || S.checkTargetClonesAttrString( LiteralLoc, CurStr, - cast(AL.getArgAsExpr(I)->IgnoreParenCasts()), + cast(AL.getArgAsExpr(I)->IgnoreParenCasts()), D, HasDefault, HasCommas, HasNotDefault, StringsBuffer)) return; } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index ab8a967b06a456f59a3a0541f0db1daeadab59e6..ba233c9e2f35d68a9d2e01e91d8f7065b44f4967 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5998,6 +5998,10 @@ void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) { if (CXXConstructorDecl *Constructor = dyn_cast(CDtorDecl)) { + if (CXXRecordDecl *ClassDecl = Constructor->getParent(); + !ClassDecl || ClassDecl->isInvalidDecl()) { + return; + } SetCtorInitializers(Constructor, /*AnyErrors=*/false); DiagnoseUninitializedFields(*this, Constructor); } @@ -14038,6 +14042,9 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = Constructor->getParent(); assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); + if (ClassDecl->isInvalidDecl()) { + return; + } SynthesizedFunctionScope Scope(*this, Constructor); @@ -19294,7 +19301,16 @@ void Sema::ActOnStartFunctionDeclarationDeclarator( ExplicitLists, /*IsFriend=*/false, IsMemberSpecialization, IsInvalid, /*SuppressDiagnostic=*/true); } - if (ExplicitParams) { + // C++23 [dcl.fct]p23: + // An abbreviated function template can have a template-head. The invented + // template-parameters are appended to the template-parameter-list after + // the explicitly declared template-parameters. + // + // A template-head must have one or more template-parameters (read: + // 'template<>' is *not* a template-head). Only append the invented + // template parameters if we matched the nested-name-specifier to a non-empty + // TemplateParameterList. + if (ExplicitParams && !ExplicitParams->empty()) { Info.AutoTemplateParameterDepth = ExplicitParams->getDepth(); llvm::append_range(Info.TemplateParams, *ExplicitParams); Info.NumExplicitTemplateParams = ExplicitParams->size(); diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 8d58ef5ee16d52d331f740495b4379c8cb85512f..3563b4f683f0794a60025c2bebbfd16d6c51b38f 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -1423,6 +1423,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) { llvm_unreachable("Invalid class for expression"); // Most statements can throw if any substatement can throw. + case Stmt::OpenACCComputeConstructClass: case Stmt::AttributedStmtClass: case Stmt::BreakStmtClass: case Stmt::CapturedStmtClass: diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 246d2313e089f307c84579941908d746ff706382..f2b89135af21cfa41fbcf5eec479dc8894ad734e 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1554,12 +1554,13 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, TemplateDeductionInfo Info(Deduce->getExprLoc()); TemplateDeductionResult Result = DeduceAutoType(TInfo->getTypeLoc(), Deduce, DeducedType, Info); - if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed) + if (Result != TemplateDeductionResult::Success && + Result != TemplateDeductionResult::AlreadyDiagnosed) return ExprError(Diag(TyBeginLoc, diag::err_auto_expr_deduction_failure) << Ty << Deduce->getType() << FullRange << Deduce->getSourceRange()); if (DeducedType.isNull()) { - assert(Result == TDK_AlreadyDiagnosed); + assert(Result == TemplateDeductionResult::AlreadyDiagnosed); return ExprError(); } @@ -2098,12 +2099,13 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, TemplateDeductionInfo Info(Deduce->getExprLoc()); TemplateDeductionResult Result = DeduceAutoType(AllocTypeInfo->getTypeLoc(), Deduce, DeducedType, Info); - if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed) + if (Result != TemplateDeductionResult::Success && + Result != TemplateDeductionResult::AlreadyDiagnosed) return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure) << AllocType << Deduce->getType() << TypeRange << Deduce->getSourceRange()); if (DeducedType.isNull()) { - assert(Result == TDK_AlreadyDiagnosed); + assert(Result == TemplateDeductionResult::AlreadyDiagnosed); return ExprError(); } AllocType = DeducedType; @@ -2883,7 +2885,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // expected function type. TemplateDeductionInfo Info(StartLoc); if (DeduceTemplateArguments(FnTmpl, nullptr, ExpectedFunctionType, Fn, - Info)) + Info) != TemplateDeductionResult::Success) continue; } else Fn = cast((*D)->getUnderlyingDecl()); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 02b1a045df44c20f4d37a7c616596a9c78dad89a..d3a9c7abd0e94465f307691e6ba7b0ed2962de48 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1200,8 +1200,8 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { // Perform template argument deduction against the type that we would // expect the function to have. if (R.getSema().DeduceTemplateArguments(ConvTemplate, nullptr, ExpectedType, - Specialization, Info) - == Sema::TDK_Success) { + Specialization, Info) == + TemplateDeductionResult::Success) { R.addDecl(Specialization); Found = true; } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 42960c229077c3e1dd674b901d2cd1493a3b1c13..9381b8c6626b649a810592db76e4886f7a995027 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -628,28 +628,28 @@ namespace { /// to the form used in overload-candidate information. DeductionFailureInfo clang::MakeDeductionFailureInfo(ASTContext &Context, - Sema::TemplateDeductionResult TDK, + TemplateDeductionResult TDK, TemplateDeductionInfo &Info) { DeductionFailureInfo Result; Result.Result = static_cast(TDK); Result.HasDiagnostic = false; switch (TDK) { - case Sema::TDK_Invalid: - case Sema::TDK_InstantiationDepth: - case Sema::TDK_TooManyArguments: - case Sema::TDK_TooFewArguments: - case Sema::TDK_MiscellaneousDeductionFailure: - case Sema::TDK_CUDATargetMismatch: + case TemplateDeductionResult::Invalid: + case TemplateDeductionResult::InstantiationDepth: + case TemplateDeductionResult::TooManyArguments: + case TemplateDeductionResult::TooFewArguments: + case TemplateDeductionResult::MiscellaneousDeductionFailure: + case TemplateDeductionResult::CUDATargetMismatch: Result.Data = nullptr; break; - case Sema::TDK_Incomplete: - case Sema::TDK_InvalidExplicitArguments: + case TemplateDeductionResult::Incomplete: + case TemplateDeductionResult::InvalidExplicitArguments: Result.Data = Info.Param.getOpaqueValue(); break; - case Sema::TDK_DeducedMismatch: - case Sema::TDK_DeducedMismatchNested: { + case TemplateDeductionResult::DeducedMismatch: + case TemplateDeductionResult::DeducedMismatchNested: { // FIXME: Should allocate from normal heap so that we can free this later. auto *Saved = new (Context) DFIDeducedMismatchArgs; Saved->FirstArg = Info.FirstArg; @@ -660,7 +660,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context, break; } - case Sema::TDK_NonDeducedMismatch: { + case TemplateDeductionResult::NonDeducedMismatch: { // FIXME: Should allocate from normal heap so that we can free this later. DFIArguments *Saved = new (Context) DFIArguments; Saved->FirstArg = Info.FirstArg; @@ -669,10 +669,10 @@ clang::MakeDeductionFailureInfo(ASTContext &Context, break; } - case Sema::TDK_IncompletePack: + case TemplateDeductionResult::IncompletePack: // FIXME: It's slightly wasteful to allocate two TemplateArguments for this. - case Sema::TDK_Inconsistent: - case Sema::TDK_Underqualified: { + case TemplateDeductionResult::Inconsistent: + case TemplateDeductionResult::Underqualified: { // FIXME: Should allocate from normal heap so that we can free this later. DFIParamWithArguments *Saved = new (Context) DFIParamWithArguments; Saved->Param = Info.Param; @@ -682,7 +682,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context, break; } - case Sema::TDK_SubstitutionFailure: + case TemplateDeductionResult::SubstitutionFailure: Result.Data = Info.takeSugared(); if (Info.hasSFINAEDiagnostic()) { PartialDiagnosticAt *Diag = new (Result.Diagnostic) PartialDiagnosticAt( @@ -692,7 +692,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context, } break; - case Sema::TDK_ConstraintsNotSatisfied: { + case TemplateDeductionResult::ConstraintsNotSatisfied: { CNSInfo *Saved = new (Context) CNSInfo; Saved->TemplateArgs = Info.takeSugared(); Saved->Satisfaction = Info.AssociatedConstraintsSatisfaction; @@ -700,9 +700,9 @@ clang::MakeDeductionFailureInfo(ASTContext &Context, break; } - case Sema::TDK_Success: - case Sema::TDK_NonDependentConversionFailure: - case Sema::TDK_AlreadyDiagnosed: + case TemplateDeductionResult::Success: + case TemplateDeductionResult::NonDependentConversionFailure: + case TemplateDeductionResult::AlreadyDiagnosed: llvm_unreachable("not a deduction failure"); } @@ -710,29 +710,29 @@ clang::MakeDeductionFailureInfo(ASTContext &Context, } void DeductionFailureInfo::Destroy() { - switch (static_cast(Result)) { - case Sema::TDK_Success: - case Sema::TDK_Invalid: - case Sema::TDK_InstantiationDepth: - case Sema::TDK_Incomplete: - case Sema::TDK_TooManyArguments: - case Sema::TDK_TooFewArguments: - case Sema::TDK_InvalidExplicitArguments: - case Sema::TDK_CUDATargetMismatch: - case Sema::TDK_NonDependentConversionFailure: + switch (static_cast(Result)) { + case TemplateDeductionResult::Success: + case TemplateDeductionResult::Invalid: + case TemplateDeductionResult::InstantiationDepth: + case TemplateDeductionResult::Incomplete: + case TemplateDeductionResult::TooManyArguments: + case TemplateDeductionResult::TooFewArguments: + case TemplateDeductionResult::InvalidExplicitArguments: + case TemplateDeductionResult::CUDATargetMismatch: + case TemplateDeductionResult::NonDependentConversionFailure: break; - case Sema::TDK_IncompletePack: - case Sema::TDK_Inconsistent: - case Sema::TDK_Underqualified: - case Sema::TDK_DeducedMismatch: - case Sema::TDK_DeducedMismatchNested: - case Sema::TDK_NonDeducedMismatch: + case TemplateDeductionResult::IncompletePack: + case TemplateDeductionResult::Inconsistent: + case TemplateDeductionResult::Underqualified: + case TemplateDeductionResult::DeducedMismatch: + case TemplateDeductionResult::DeducedMismatchNested: + case TemplateDeductionResult::NonDeducedMismatch: // FIXME: Destroy the data? Data = nullptr; break; - case Sema::TDK_SubstitutionFailure: + case TemplateDeductionResult::SubstitutionFailure: // FIXME: Destroy the template argument list? Data = nullptr; if (PartialDiagnosticAt *Diag = getSFINAEDiagnostic()) { @@ -741,7 +741,7 @@ void DeductionFailureInfo::Destroy() { } break; - case Sema::TDK_ConstraintsNotSatisfied: + case TemplateDeductionResult::ConstraintsNotSatisfied: // FIXME: Destroy the template argument list? Data = nullptr; if (PartialDiagnosticAt *Diag = getSFINAEDiagnostic()) { @@ -751,8 +751,8 @@ void DeductionFailureInfo::Destroy() { break; // Unhandled - case Sema::TDK_MiscellaneousDeductionFailure: - case Sema::TDK_AlreadyDiagnosed: + case TemplateDeductionResult::MiscellaneousDeductionFailure: + case TemplateDeductionResult::AlreadyDiagnosed: break; } } @@ -764,33 +764,33 @@ PartialDiagnosticAt *DeductionFailureInfo::getSFINAEDiagnostic() { } TemplateParameter DeductionFailureInfo::getTemplateParameter() { - switch (static_cast(Result)) { - case Sema::TDK_Success: - case Sema::TDK_Invalid: - case Sema::TDK_InstantiationDepth: - case Sema::TDK_TooManyArguments: - case Sema::TDK_TooFewArguments: - case Sema::TDK_SubstitutionFailure: - case Sema::TDK_DeducedMismatch: - case Sema::TDK_DeducedMismatchNested: - case Sema::TDK_NonDeducedMismatch: - case Sema::TDK_CUDATargetMismatch: - case Sema::TDK_NonDependentConversionFailure: - case Sema::TDK_ConstraintsNotSatisfied: + switch (static_cast(Result)) { + case TemplateDeductionResult::Success: + case TemplateDeductionResult::Invalid: + case TemplateDeductionResult::InstantiationDepth: + case TemplateDeductionResult::TooManyArguments: + case TemplateDeductionResult::TooFewArguments: + case TemplateDeductionResult::SubstitutionFailure: + case TemplateDeductionResult::DeducedMismatch: + case TemplateDeductionResult::DeducedMismatchNested: + case TemplateDeductionResult::NonDeducedMismatch: + case TemplateDeductionResult::CUDATargetMismatch: + case TemplateDeductionResult::NonDependentConversionFailure: + case TemplateDeductionResult::ConstraintsNotSatisfied: return TemplateParameter(); - case Sema::TDK_Incomplete: - case Sema::TDK_InvalidExplicitArguments: + case TemplateDeductionResult::Incomplete: + case TemplateDeductionResult::InvalidExplicitArguments: return TemplateParameter::getFromOpaqueValue(Data); - case Sema::TDK_IncompletePack: - case Sema::TDK_Inconsistent: - case Sema::TDK_Underqualified: + case TemplateDeductionResult::IncompletePack: + case TemplateDeductionResult::Inconsistent: + case TemplateDeductionResult::Underqualified: return static_cast(Data)->Param; // Unhandled - case Sema::TDK_MiscellaneousDeductionFailure: - case Sema::TDK_AlreadyDiagnosed: + case TemplateDeductionResult::MiscellaneousDeductionFailure: + case TemplateDeductionResult::AlreadyDiagnosed: break; } @@ -798,35 +798,35 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() { } TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() { - switch (static_cast(Result)) { - case Sema::TDK_Success: - case Sema::TDK_Invalid: - case Sema::TDK_InstantiationDepth: - case Sema::TDK_TooManyArguments: - case Sema::TDK_TooFewArguments: - case Sema::TDK_Incomplete: - case Sema::TDK_IncompletePack: - case Sema::TDK_InvalidExplicitArguments: - case Sema::TDK_Inconsistent: - case Sema::TDK_Underqualified: - case Sema::TDK_NonDeducedMismatch: - case Sema::TDK_CUDATargetMismatch: - case Sema::TDK_NonDependentConversionFailure: + switch (static_cast(Result)) { + case TemplateDeductionResult::Success: + case TemplateDeductionResult::Invalid: + case TemplateDeductionResult::InstantiationDepth: + case TemplateDeductionResult::TooManyArguments: + case TemplateDeductionResult::TooFewArguments: + case TemplateDeductionResult::Incomplete: + case TemplateDeductionResult::IncompletePack: + case TemplateDeductionResult::InvalidExplicitArguments: + case TemplateDeductionResult::Inconsistent: + case TemplateDeductionResult::Underqualified: + case TemplateDeductionResult::NonDeducedMismatch: + case TemplateDeductionResult::CUDATargetMismatch: + case TemplateDeductionResult::NonDependentConversionFailure: return nullptr; - case Sema::TDK_DeducedMismatch: - case Sema::TDK_DeducedMismatchNested: + case TemplateDeductionResult::DeducedMismatch: + case TemplateDeductionResult::DeducedMismatchNested: return static_cast(Data)->TemplateArgs; - case Sema::TDK_SubstitutionFailure: + case TemplateDeductionResult::SubstitutionFailure: return static_cast(Data); - case Sema::TDK_ConstraintsNotSatisfied: + case TemplateDeductionResult::ConstraintsNotSatisfied: return static_cast(Data)->TemplateArgs; // Unhandled - case Sema::TDK_MiscellaneousDeductionFailure: - case Sema::TDK_AlreadyDiagnosed: + case TemplateDeductionResult::MiscellaneousDeductionFailure: + case TemplateDeductionResult::AlreadyDiagnosed: break; } @@ -834,31 +834,31 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() { } const TemplateArgument *DeductionFailureInfo::getFirstArg() { - switch (static_cast(Result)) { - case Sema::TDK_Success: - case Sema::TDK_Invalid: - case Sema::TDK_InstantiationDepth: - case Sema::TDK_Incomplete: - case Sema::TDK_TooManyArguments: - case Sema::TDK_TooFewArguments: - case Sema::TDK_InvalidExplicitArguments: - case Sema::TDK_SubstitutionFailure: - case Sema::TDK_CUDATargetMismatch: - case Sema::TDK_NonDependentConversionFailure: - case Sema::TDK_ConstraintsNotSatisfied: + switch (static_cast(Result)) { + case TemplateDeductionResult::Success: + case TemplateDeductionResult::Invalid: + case TemplateDeductionResult::InstantiationDepth: + case TemplateDeductionResult::Incomplete: + case TemplateDeductionResult::TooManyArguments: + case TemplateDeductionResult::TooFewArguments: + case TemplateDeductionResult::InvalidExplicitArguments: + case TemplateDeductionResult::SubstitutionFailure: + case TemplateDeductionResult::CUDATargetMismatch: + case TemplateDeductionResult::NonDependentConversionFailure: + case TemplateDeductionResult::ConstraintsNotSatisfied: return nullptr; - case Sema::TDK_IncompletePack: - case Sema::TDK_Inconsistent: - case Sema::TDK_Underqualified: - case Sema::TDK_DeducedMismatch: - case Sema::TDK_DeducedMismatchNested: - case Sema::TDK_NonDeducedMismatch: + case TemplateDeductionResult::IncompletePack: + case TemplateDeductionResult::Inconsistent: + case TemplateDeductionResult::Underqualified: + case TemplateDeductionResult::DeducedMismatch: + case TemplateDeductionResult::DeducedMismatchNested: + case TemplateDeductionResult::NonDeducedMismatch: return &static_cast(Data)->FirstArg; // Unhandled - case Sema::TDK_MiscellaneousDeductionFailure: - case Sema::TDK_AlreadyDiagnosed: + case TemplateDeductionResult::MiscellaneousDeductionFailure: + case TemplateDeductionResult::AlreadyDiagnosed: break; } @@ -866,31 +866,31 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() { } const TemplateArgument *DeductionFailureInfo::getSecondArg() { - switch (static_cast(Result)) { - case Sema::TDK_Success: - case Sema::TDK_Invalid: - case Sema::TDK_InstantiationDepth: - case Sema::TDK_Incomplete: - case Sema::TDK_IncompletePack: - case Sema::TDK_TooManyArguments: - case Sema::TDK_TooFewArguments: - case Sema::TDK_InvalidExplicitArguments: - case Sema::TDK_SubstitutionFailure: - case Sema::TDK_CUDATargetMismatch: - case Sema::TDK_NonDependentConversionFailure: - case Sema::TDK_ConstraintsNotSatisfied: + switch (static_cast(Result)) { + case TemplateDeductionResult::Success: + case TemplateDeductionResult::Invalid: + case TemplateDeductionResult::InstantiationDepth: + case TemplateDeductionResult::Incomplete: + case TemplateDeductionResult::IncompletePack: + case TemplateDeductionResult::TooManyArguments: + case TemplateDeductionResult::TooFewArguments: + case TemplateDeductionResult::InvalidExplicitArguments: + case TemplateDeductionResult::SubstitutionFailure: + case TemplateDeductionResult::CUDATargetMismatch: + case TemplateDeductionResult::NonDependentConversionFailure: + case TemplateDeductionResult::ConstraintsNotSatisfied: return nullptr; - case Sema::TDK_Inconsistent: - case Sema::TDK_Underqualified: - case Sema::TDK_DeducedMismatch: - case Sema::TDK_DeducedMismatchNested: - case Sema::TDK_NonDeducedMismatch: + case TemplateDeductionResult::Inconsistent: + case TemplateDeductionResult::Underqualified: + case TemplateDeductionResult::DeducedMismatch: + case TemplateDeductionResult::DeducedMismatchNested: + case TemplateDeductionResult::NonDeducedMismatch: return &static_cast(Data)->SecondArg; // Unhandled - case Sema::TDK_MiscellaneousDeductionFailure: - case Sema::TDK_AlreadyDiagnosed: + case TemplateDeductionResult::MiscellaneousDeductionFailure: + case TemplateDeductionResult::AlreadyDiagnosed: break; } @@ -898,9 +898,9 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() { } std::optional DeductionFailureInfo::getCallArgIndex() { - switch (static_cast(Result)) { - case Sema::TDK_DeducedMismatch: - case Sema::TDK_DeducedMismatchNested: + switch (static_cast(Result)) { + case TemplateDeductionResult::DeducedMismatch: + case TemplateDeductionResult::DeducedMismatchNested: return static_cast(Data)->CallArgIndex; default: @@ -7548,12 +7548,14 @@ void Sema::AddMethodTemplateCandidate( if (TemplateDeductionResult Result = DeduceTemplateArguments( MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info, PartialOverloading, /*AggregateDeductionCandidate=*/false, ObjectType, - ObjectClassification, [&](ArrayRef ParamTypes) { + ObjectClassification, + [&](ArrayRef ParamTypes) { return CheckNonDependentConversions( MethodTmpl, ParamTypes, Args, CandidateSet, Conversions, SuppressUserConversions, ActingContext, ObjectType, ObjectClassification, PO); - })) { + }); + Result != TemplateDeductionResult::Success) { OverloadCandidate &Candidate = CandidateSet.addCandidate(Conversions.size(), Conversions); Candidate.FoundDecl = FoundDecl; @@ -7566,7 +7568,7 @@ void Sema::AddMethodTemplateCandidate( cast(Candidate.Function)->isStatic() || ObjectType.isNull(); Candidate.ExplicitCallArguments = Args.size(); - if (Result == TDK_NonDependentConversionFailure) + if (Result == TemplateDeductionResult::NonDependentConversionFailure) Candidate.FailureKind = ovl_fail_bad_conversion; else { Candidate.FailureKind = ovl_fail_bad_deduction; @@ -7639,7 +7641,8 @@ void Sema::AddTemplateOverloadCandidate( return CheckNonDependentConversions( FunctionTemplate, ParamTypes, Args, CandidateSet, Conversions, SuppressUserConversions, nullptr, QualType(), {}, PO); - })) { + }); + Result != TemplateDeductionResult::Success) { OverloadCandidate &Candidate = CandidateSet.addCandidate(Conversions.size(), Conversions); Candidate.FoundDecl = FoundDecl; @@ -7655,7 +7658,7 @@ void Sema::AddTemplateOverloadCandidate( isa(Candidate.Function) && !isa(Candidate.Function); Candidate.ExplicitCallArguments = Args.size(); - if (Result == TDK_NonDependentConversionFailure) + if (Result == TemplateDeductionResult::NonDependentConversionFailure) Candidate.FailureKind = ovl_fail_bad_conversion; else { Candidate.FailureKind = ovl_fail_bad_deduction; @@ -8042,7 +8045,8 @@ void Sema::AddTemplateConversionCandidate( CXXConversionDecl *Specialization = nullptr; if (TemplateDeductionResult Result = DeduceTemplateArguments( FunctionTemplate, ObjectType, ObjectClassification, ToType, - Specialization, Info)) { + Specialization, Info); + Result != TemplateDeductionResult::Success) { OverloadCandidate &Candidate = CandidateSet.addCandidate(); Candidate.FoundDecl = FoundDecl; Candidate.Function = FunctionTemplate->getTemplatedDecl(); @@ -10655,7 +10659,8 @@ void Sema::diagnoseEquivalentInternalLinkageDeclarations( bool OverloadCandidate::NotValidBecauseConstraintExprHasError() const { return FailureKind == ovl_fail_bad_deduction && - DeductionFailure.Result == Sema::TDK_ConstraintsNotSatisfied && + static_cast(DeductionFailure.Result) == + TemplateDeductionResult::ConstraintsNotSatisfied && static_cast(DeductionFailure.Data) ->Satisfaction.ContainsErrors; } @@ -11358,11 +11363,13 @@ static bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand, if (NumArgs < MinParams) { assert((Cand->FailureKind == ovl_fail_too_few_arguments) || (Cand->FailureKind == ovl_fail_bad_deduction && - Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments)); + Cand->DeductionFailure.getResult() == + TemplateDeductionResult::TooFewArguments)); } else { assert((Cand->FailureKind == ovl_fail_too_many_arguments) || (Cand->FailureKind == ovl_fail_bad_deduction && - Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments)); + Cand->DeductionFailure.getResult() == + TemplateDeductionResult::TooManyArguments)); } return false; @@ -11445,11 +11452,18 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, (ParamD = Param.dyn_cast()) || (ParamD = Param.dyn_cast()) || (ParamD = Param.dyn_cast()); - switch (DeductionFailure.Result) { - case Sema::TDK_Success: - llvm_unreachable("TDK_success while diagnosing bad deduction"); + switch (DeductionFailure.getResult()) { + case TemplateDeductionResult::Success: + llvm_unreachable( + "TemplateDeductionResult::Success while diagnosing bad deduction"); + case TemplateDeductionResult::NonDependentConversionFailure: + llvm_unreachable("TemplateDeductionResult::NonDependentConversionFailure " + "while diagnosing bad deduction"); + case TemplateDeductionResult::Invalid: + case TemplateDeductionResult::AlreadyDiagnosed: + return; - case Sema::TDK_Incomplete: { + case TemplateDeductionResult::Incomplete: { assert(ParamD && "no parameter found for incomplete deduction result"); S.Diag(Templated->getLocation(), diag::note_ovl_candidate_incomplete_deduction) @@ -11458,7 +11472,7 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, return; } - case Sema::TDK_IncompletePack: { + case TemplateDeductionResult::IncompletePack: { assert(ParamD && "no parameter found for incomplete deduction result"); S.Diag(Templated->getLocation(), diag::note_ovl_candidate_incomplete_deduction_pack) @@ -11469,7 +11483,7 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, return; } - case Sema::TDK_Underqualified: { + case TemplateDeductionResult::Underqualified: { assert(ParamD && "no parameter found for bad qualifiers deduction result"); TemplateTypeParmDecl *TParam = cast(ParamD); @@ -11494,7 +11508,7 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, return; } - case Sema::TDK_Inconsistent: { + case TemplateDeductionResult::Inconsistent: { assert(ParamD && "no parameter found for inconsistent deduction result"); int which = 0; if (isa(ParamD)) @@ -11539,7 +11553,7 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, return; } - case Sema::TDK_InvalidExplicitArguments: + case TemplateDeductionResult::InvalidExplicitArguments: assert(ParamD && "no parameter found for invalid explicit arguments"); if (ParamD->getDeclName()) S.Diag(Templated->getLocation(), @@ -11561,7 +11575,7 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, MaybeEmitInheritedConstructorNote(S, Found); return; - case Sema::TDK_ConstraintsNotSatisfied: { + case TemplateDeductionResult::ConstraintsNotSatisfied: { // Format the template argument list into the argument string. SmallString<128> TemplateArgString; TemplateArgumentList *Args = DeductionFailure.getTemplateArgumentList(); @@ -11578,18 +11592,18 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, static_cast(DeductionFailure.Data)->Satisfaction); return; } - case Sema::TDK_TooManyArguments: - case Sema::TDK_TooFewArguments: + case TemplateDeductionResult::TooManyArguments: + case TemplateDeductionResult::TooFewArguments: DiagnoseArityMismatch(S, Found, Templated, NumArgs); return; - case Sema::TDK_InstantiationDepth: + case TemplateDeductionResult::InstantiationDepth: S.Diag(Templated->getLocation(), diag::note_ovl_candidate_instantiation_depth); MaybeEmitInheritedConstructorNote(S, Found); return; - case Sema::TDK_SubstitutionFailure: { + case TemplateDeductionResult::SubstitutionFailure: { // Format the template argument list into the argument string. SmallString<128> TemplateArgString; if (TemplateArgumentList *Args = @@ -11639,8 +11653,8 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, return; } - case Sema::TDK_DeducedMismatch: - case Sema::TDK_DeducedMismatchNested: { + case TemplateDeductionResult::DeducedMismatch: + case TemplateDeductionResult::DeducedMismatchNested: { // Format the template argument list into the argument string. SmallString<128> TemplateArgString; if (TemplateArgumentList *Args = @@ -11656,11 +11670,12 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, << (*DeductionFailure.getCallArgIndex() + 1) << *DeductionFailure.getFirstArg() << *DeductionFailure.getSecondArg() << TemplateArgString - << (DeductionFailure.Result == Sema::TDK_DeducedMismatchNested); + << (DeductionFailure.getResult() == + TemplateDeductionResult::DeducedMismatchNested); break; } - case Sema::TDK_NonDeducedMismatch: { + case TemplateDeductionResult::NonDeducedMismatch: { // FIXME: Provide a source location to indicate what we couldn't match. TemplateArgument FirstTA = *DeductionFailure.getFirstArg(); TemplateArgument SecondTA = *DeductionFailure.getSecondArg(); @@ -11701,11 +11716,11 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, } // TODO: diagnose these individually, then kill off // note_ovl_candidate_bad_deduction, which is uselessly vague. - case Sema::TDK_MiscellaneousDeductionFailure: + case TemplateDeductionResult::MiscellaneousDeductionFailure: S.Diag(Templated->getLocation(), diag::note_ovl_candidate_bad_deduction); MaybeEmitInheritedConstructorNote(S, Found); return; - case Sema::TDK_CUDATargetMismatch: + case TemplateDeductionResult::CUDATargetMismatch: S.Diag(Templated->getLocation(), diag::note_cuda_ovl_candidate_target_mismatch); return; @@ -11716,8 +11731,9 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, static void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, unsigned NumArgs, bool TakingCandidateAddress) { - unsigned TDK = Cand->DeductionFailure.Result; - if (TDK == Sema::TDK_TooFewArguments || TDK == Sema::TDK_TooManyArguments) { + TemplateDeductionResult TDK = Cand->DeductionFailure.getResult(); + if (TDK == TemplateDeductionResult::TooFewArguments || + TDK == TemplateDeductionResult::TooManyArguments) { if (CheckArityMismatch(S, Cand, NumArgs)) return; } @@ -12051,38 +12067,38 @@ static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) { } static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) { - switch ((Sema::TemplateDeductionResult)DFI.Result) { - case Sema::TDK_Success: - case Sema::TDK_NonDependentConversionFailure: - case Sema::TDK_AlreadyDiagnosed: + switch (static_cast(DFI.Result)) { + case TemplateDeductionResult::Success: + case TemplateDeductionResult::NonDependentConversionFailure: + case TemplateDeductionResult::AlreadyDiagnosed: llvm_unreachable("non-deduction failure while diagnosing bad deduction"); - case Sema::TDK_Invalid: - case Sema::TDK_Incomplete: - case Sema::TDK_IncompletePack: + case TemplateDeductionResult::Invalid: + case TemplateDeductionResult::Incomplete: + case TemplateDeductionResult::IncompletePack: return 1; - case Sema::TDK_Underqualified: - case Sema::TDK_Inconsistent: + case TemplateDeductionResult::Underqualified: + case TemplateDeductionResult::Inconsistent: return 2; - case Sema::TDK_SubstitutionFailure: - case Sema::TDK_DeducedMismatch: - case Sema::TDK_ConstraintsNotSatisfied: - case Sema::TDK_DeducedMismatchNested: - case Sema::TDK_NonDeducedMismatch: - case Sema::TDK_MiscellaneousDeductionFailure: - case Sema::TDK_CUDATargetMismatch: + case TemplateDeductionResult::SubstitutionFailure: + case TemplateDeductionResult::DeducedMismatch: + case TemplateDeductionResult::ConstraintsNotSatisfied: + case TemplateDeductionResult::DeducedMismatchNested: + case TemplateDeductionResult::NonDeducedMismatch: + case TemplateDeductionResult::MiscellaneousDeductionFailure: + case TemplateDeductionResult::CUDATargetMismatch: return 3; - case Sema::TDK_InstantiationDepth: + case TemplateDeductionResult::InstantiationDepth: return 4; - case Sema::TDK_InvalidExplicitArguments: + case TemplateDeductionResult::InvalidExplicitArguments: return 5; - case Sema::TDK_TooManyArguments: - case Sema::TDK_TooFewArguments: + case TemplateDeductionResult::TooManyArguments: + case TemplateDeductionResult::TooFewArguments: return 6; } llvm_unreachable("Unhandled deduction result"); @@ -12810,11 +12826,10 @@ private: // overloaded functions considered. FunctionDecl *Specialization = nullptr; TemplateDeductionInfo Info(FailedCandidates.getLocation()); - if (Sema::TemplateDeductionResult Result - = S.DeduceTemplateArguments(FunctionTemplate, - &OvlExplicitTemplateArgs, - TargetFunctionType, Specialization, - Info, /*IsAddressOfFunction*/true)) { + if (TemplateDeductionResult Result = S.DeduceTemplateArguments( + FunctionTemplate, &OvlExplicitTemplateArgs, TargetFunctionType, + Specialization, Info, /*IsAddressOfFunction*/ true); + Result != TemplateDeductionResult::Success) { // Make a note of the failed deduction for diagnostics. FailedCandidates.addCandidate() .set(CurAccessFunPair, FunctionTemplate->getTemplatedDecl(), @@ -13305,10 +13320,10 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization( // overloaded functions considered. FunctionDecl *Specialization = nullptr; TemplateDeductionInfo Info(ovl->getNameLoc()); - if (TemplateDeductionResult Result - = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs, - Specialization, Info, - /*IsAddressOfFunction*/true)) { + if (TemplateDeductionResult Result = DeduceTemplateArguments( + FunctionTemplate, &ExplicitTemplateArgs, Specialization, Info, + /*IsAddressOfFunction*/ true); + Result != TemplateDeductionResult::Success) { // Make a note of the failed deduction for diagnostics. if (FailedTSC) FailedTSC->addCandidate().set( diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 5ab25344921130d3bcd6da7cf62e4bd2dc172e28..dde3bd84e89f8be7e0612a1e7336ffc71b727bb2 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -2326,7 +2326,8 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, FirstType = QualType(); TemplateDeductionResult Result = DeduceAutoType( D->getTypeSourceInfo()->getTypeLoc(), DeducedInit, FirstType, Info); - if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed) + if (Result != TemplateDeductionResult::Success && + Result != TemplateDeductionResult::AlreadyDiagnosed) DiagnoseAutoDeductionFailure(D, DeducedInit); if (FirstType.isNull()) { D->setInvalidDecl(); @@ -2394,9 +2395,10 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, SemaRef.Diag(Loc, DiagID) << Init->getType(); } else { TemplateDeductionInfo Info(Init->getExprLoc()); - Sema::TemplateDeductionResult Result = SemaRef.DeduceAutoType( + TemplateDeductionResult Result = SemaRef.DeduceAutoType( Decl->getTypeSourceInfo()->getTypeLoc(), Init, InitType, Info); - if (Result != Sema::TDK_Success && Result != Sema::TDK_AlreadyDiagnosed) + if (Result != TemplateDeductionResult::Success && + Result != TemplateDeductionResult::AlreadyDiagnosed) SemaRef.Diag(Loc, DiagID) << Init->getType(); } @@ -3865,14 +3867,14 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, TemplateDeductionResult Res = DeduceAutoType( OrigResultType, RetExpr, Deduced, Info, /*DependentDeduction=*/false, /*IgnoreConstraints=*/false, &FailedTSC); - if (Res != TDK_Success && FD->isInvalidDecl()) + if (Res != TemplateDeductionResult::Success && FD->isInvalidDecl()) return true; switch (Res) { - case TDK_Success: + case TemplateDeductionResult::Success: break; - case TDK_AlreadyDiagnosed: + case TemplateDeductionResult::AlreadyDiagnosed: return true; - case TDK_Inconsistent: { + case TemplateDeductionResult::Inconsistent: { // If a function with a declared return type that contains a placeholder // type has multiple return statements, the return type is deduced for // each return statement. [...] if the type deduced is not the same in @@ -4381,6 +4383,7 @@ Sema::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) { namespace { class CatchHandlerType { QualType QT; + LLVM_PREFERRED_TYPE(bool) unsigned IsPointer : 1; // This is a special constructor to be used only with DenseMapInfo's diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index cf781e0e1bf3f4a79142a438f9ddc16b08e848a7..9e516da2aa27a12f7736f64ebf00d68b3456e144 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4863,7 +4863,8 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, TemplateDeductionInfo Info(FailedCandidates.getLocation()); if (TemplateDeductionResult Result = - DeduceTemplateArguments(Partial, CanonicalConverted, Info)) { + DeduceTemplateArguments(Partial, CanonicalConverted, Info); + Result != TemplateDeductionResult::Success) { // Store the failed-deduction information for use in diagnostics, later. // TODO: Actually use the failed-deduction info? FailedCandidates.addCandidate().set( @@ -7243,10 +7244,10 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // along with the other associated constraints after // checking the template argument list. /*IgnoreConstraints=*/true); - if (Result == TDK_AlreadyDiagnosed) { + if (Result == TemplateDeductionResult::AlreadyDiagnosed) { if (ParamType.isNull()) return ExprError(); - } else if (Result != TDK_Success) { + } else if (Result != TemplateDeductionResult::Success) { Diag(Arg->getExprLoc(), diag::err_non_type_template_parm_type_deduction_failure) << Param->getDeclName() << Param->getType() << Arg->getType() @@ -9644,8 +9645,8 @@ bool Sema::CheckFunctionTemplateSpecialization( FunctionDecl *Specialization = nullptr; if (TemplateDeductionResult TDK = DeduceTemplateArguments( cast(FunTmpl->getFirstDecl()), - ExplicitTemplateArgs ? &Args : nullptr, FT, Specialization, - Info)) { + ExplicitTemplateArgs ? &Args : nullptr, FT, Specialization, Info); + TDK != TemplateDeductionResult::Success) { // Template argument deduction failed; record why it failed, so // that we can provide nifty diagnostics. FailedCandidates.addCandidate().set( @@ -9666,7 +9667,8 @@ bool Sema::CheckFunctionTemplateSpecialization( IdentifyCUDATarget(FD, /* IgnoreImplicitHDAttr = */ true)) { FailedCandidates.addCandidate().set( I.getPair(), FunTmpl->getTemplatedDecl(), - MakeDeductionFailureInfo(Context, TDK_CUDATargetMismatch, Info)); + MakeDeductionFailureInfo( + Context, TemplateDeductionResult::CUDATargetMismatch, Info)); continue; } @@ -10816,11 +10818,10 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, TemplateDeductionInfo Info(FailedCandidates.getLocation()); FunctionDecl *Specialization = nullptr; - if (TemplateDeductionResult TDK - = DeduceTemplateArguments(FunTmpl, - (HasExplicitTemplateArgs ? &TemplateArgs - : nullptr), - R, Specialization, Info)) { + if (TemplateDeductionResult TDK = DeduceTemplateArguments( + FunTmpl, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr), R, + Specialization, Info); + TDK != TemplateDeductionResult::Success) { // Keep track of almost-matches. FailedCandidates.addCandidate() .set(P.getPair(), FunTmpl->getTemplatedDecl(), @@ -10840,7 +10841,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, IdentifyCUDATarget(D.getDeclSpec().getAttributes())) { FailedCandidates.addCandidate().set( P.getPair(), FunTmpl->getTemplatedDecl(), - MakeDeductionFailureInfo(Context, TDK_CUDATargetMismatch, Info)); + MakeDeductionFailureInfo( + Context, TemplateDeductionResult::CUDATargetMismatch, Info)); continue; } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index a54ad27975890aef18c2ef6e405bfa3e7708ddf5..47cc22310c4eec0233efb4feb4dff90ad59b922c 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -133,13 +133,13 @@ static bool hasSameExtendedValue(llvm::APSInt X, llvm::APSInt Y) { return X == Y; } -static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( +static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( Sema &S, TemplateParameterList *TemplateParams, QualType Param, QualType Arg, TemplateDeductionInfo &Info, SmallVectorImpl &Deduced, unsigned TDF, bool PartialOrdering = false, bool DeducedFromArrayBound = false); -static Sema::TemplateDeductionResult +static TemplateDeductionResult DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, ArrayRef Ps, ArrayRef As, @@ -393,10 +393,11 @@ checkDeducedTemplateArguments(ASTContext &Context, /// Deduce the value of the given non-type template parameter /// as the given deduced template argument. All non-type template parameter /// deduction is funneled through here. -static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( +static TemplateDeductionResult DeduceNonTypeTemplateArgument( Sema &S, TemplateParameterList *TemplateParams, - const NonTypeTemplateParmDecl *NTTP, const DeducedTemplateArgument &NewDeduced, - QualType ValueType, TemplateDeductionInfo &Info, + const NonTypeTemplateParmDecl *NTTP, + const DeducedTemplateArgument &NewDeduced, QualType ValueType, + TemplateDeductionInfo &Info, SmallVectorImpl &Deduced) { assert(NTTP->getDepth() == Info.getDeducedDepth() && "deducing non-type template argument with wrong depth"); @@ -407,19 +408,19 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( Info.Param = const_cast(NTTP); Info.FirstArg = Deduced[NTTP->getIndex()]; Info.SecondArg = NewDeduced; - return Sema::TDK_Inconsistent; + return TemplateDeductionResult::Inconsistent; } Deduced[NTTP->getIndex()] = Result; if (!S.getLangOpts().CPlusPlus17) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; if (NTTP->isExpandedParameterPack()) // FIXME: We may still need to deduce parts of the type here! But we // don't have any way to find which slice of the type to use, and the // type stored on the NTTP itself is nonsense. Perhaps the type of an // expanded NTTP should be a pack expansion type? - return Sema::TDK_Success; + return TemplateDeductionResult::Success; // Get the type of the parameter for deduction. If it's a (dependent) array // or function type, we will not have decayed it yet, so do that now. @@ -446,7 +447,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( /// Deduce the value of the given non-type template parameter /// from the given integral constant. -static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( +static TemplateDeductionResult DeduceNonTypeTemplateArgument( Sema &S, TemplateParameterList *TemplateParams, const NonTypeTemplateParmDecl *NTTP, const llvm::APSInt &Value, QualType ValueType, bool DeducedFromArrayBound, TemplateDeductionInfo &Info, @@ -460,7 +461,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( /// Deduce the value of the given non-type template parameter /// from the given null pointer template argument type. -static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument( +static TemplateDeductionResult DeduceNullPtrTemplateArgument( Sema &S, TemplateParameterList *TemplateParams, const NonTypeTemplateParmDecl *NTTP, QualType NullPtrType, TemplateDeductionInfo &Info, @@ -481,9 +482,10 @@ static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument( /// from the given type- or value-dependent expression. /// /// \returns true if deduction succeeded, false otherwise. -static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( +static TemplateDeductionResult DeduceNonTypeTemplateArgument( Sema &S, TemplateParameterList *TemplateParams, - const NonTypeTemplateParmDecl *NTTP, Expr *Value, TemplateDeductionInfo &Info, + const NonTypeTemplateParmDecl *NTTP, Expr *Value, + TemplateDeductionInfo &Info, SmallVectorImpl &Deduced) { return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, DeducedTemplateArgument(Value), @@ -494,7 +496,7 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( /// from the given declaration. /// /// \returns true if deduction succeeded, false otherwise. -static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( +static TemplateDeductionResult DeduceNonTypeTemplateArgument( Sema &S, TemplateParameterList *TemplateParams, const NonTypeTemplateParmDecl *NTTP, ValueDecl *D, QualType T, TemplateDeductionInfo &Info, @@ -505,25 +507,23 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument( S, TemplateParams, NTTP, DeducedTemplateArgument(New), T, Info, Deduced); } -static Sema::TemplateDeductionResult -DeduceTemplateArguments(Sema &S, - TemplateParameterList *TemplateParams, - TemplateName Param, - TemplateName Arg, +static TemplateDeductionResult +DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, + TemplateName Param, TemplateName Arg, TemplateDeductionInfo &Info, SmallVectorImpl &Deduced) { TemplateDecl *ParamDecl = Param.getAsTemplateDecl(); if (!ParamDecl) { // The parameter type is dependent and is not a template template parameter, // so there is nothing that we can deduce. - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } if (TemplateTemplateParmDecl *TempParam = dyn_cast(ParamDecl)) { // If we're not deducing at this depth, there's nothing to deduce. if (TempParam->getDepth() != Info.getDeducedDepth()) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; DeducedTemplateArgument NewDeduced(S.Context.getCanonicalTemplateName(Arg)); DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context, @@ -533,21 +533,21 @@ DeduceTemplateArguments(Sema &S, Info.Param = TempParam; Info.FirstArg = Deduced[TempParam->getIndex()]; Info.SecondArg = NewDeduced; - return Sema::TDK_Inconsistent; + return TemplateDeductionResult::Inconsistent; } Deduced[TempParam->getIndex()] = Result; - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } // Verify that the two template names are equivalent. if (S.Context.hasSameTemplateName(Param, Arg)) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; // Mismatch of non-dependent template parameter to argument. Info.FirstArg = TemplateArgument(Param); Info.SecondArg = TemplateArgument(Arg); - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } /// Deduce the template arguments by comparing the template parameter @@ -568,7 +568,7 @@ DeduceTemplateArguments(Sema &S, /// \returns the result of template argument deduction so far. Note that a /// "success" result means that template argument deduction has not yet failed, /// but it may still fail, later, for other reasons. -static Sema::TemplateDeductionResult +static TemplateDeductionResult DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams, const QualType P, QualType A, TemplateDeductionInfo &Info, @@ -583,7 +583,7 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams, // If the parameter is an alias template, there is nothing to deduce. if (const auto *TD = TNP.getAsTemplateDecl(); TD && TD->isTypeAlias()) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; ArrayRef PResolved = TP->template_arguments(); @@ -600,11 +600,12 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams, // If the argument is an alias template, there is nothing to deduce. if (const auto *TD = TNA.getAsTemplateDecl(); TD && TD->isTypeAlias()) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; // Perform template argument deduction for the template name. if (auto Result = - DeduceTemplateArguments(S, TemplateParams, TNP, TNA, Info, Deduced)) + DeduceTemplateArguments(S, TemplateParams, TNP, TNA, Info, Deduced); + Result != TemplateDeductionResult::Success) return Result; // Perform template argument deduction on each template // argument. Ignore any missing/extra arguments, since they could be @@ -623,13 +624,14 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams, if (!SA) { Info.FirstArg = TemplateArgument(P); Info.SecondArg = TemplateArgument(A); - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } // Perform template argument deduction for the template name. if (auto Result = DeduceTemplateArguments( S, TemplateParams, TP->getTemplateName(), - TemplateName(SA->getSpecializedTemplate()), Info, Deduced)) + TemplateName(SA->getSpecializedTemplate()), Info, Deduced); + Result != TemplateDeductionResult::Success) return Result; // Perform template argument deduction for the template arguments. @@ -919,7 +921,7 @@ public: /// Finish template argument deduction for a set of argument packs, /// producing the argument packs and checking for consistency with prior /// deductions. - Sema::TemplateDeductionResult finish() { + TemplateDeductionResult finish() { // Build argument packs for each of the parameter packs expanded by this // pack expansion. for (auto &Pack : Packs) { @@ -996,7 +998,7 @@ public: Info.Param = makeTemplateParameter(Param); Info.FirstArg = OldPack; Info.SecondArg = NewPack; - return Sema::TDK_Inconsistent; + return TemplateDeductionResult::Inconsistent; } // If we have a pre-expanded pack and we didn't deduce enough elements @@ -1005,14 +1007,14 @@ public: if (*Expansions != PackElements) { Info.Param = makeTemplateParameter(Param); Info.FirstArg = Result; - return Sema::TDK_IncompletePack; + return TemplateDeductionResult::IncompletePack; } } *Loc = Result; } - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } private: @@ -1062,15 +1064,13 @@ private: /// \returns the result of template argument deduction so far. Note that a /// "success" result means that template argument deduction has not yet failed, /// but it may still fail, later, for other reasons. -static Sema::TemplateDeductionResult -DeduceTemplateArguments(Sema &S, - TemplateParameterList *TemplateParams, +static TemplateDeductionResult +DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, const QualType *Params, unsigned NumParams, const QualType *Args, unsigned NumArgs, TemplateDeductionInfo &Info, SmallVectorImpl &Deduced, - unsigned TDF, - bool PartialOrdering = false) { + unsigned TDF, bool PartialOrdering = false) { // C++0x [temp.deduct.type]p10: // Similarly, if P has a form that contains (T), then each parameter type // Pi of the respective parameter-type- list of P is compared with the @@ -1086,22 +1086,22 @@ DeduceTemplateArguments(Sema &S, // Make sure we have an argument. if (ArgIdx >= NumArgs) - return Sema::TDK_MiscellaneousDeductionFailure; + return TemplateDeductionResult::MiscellaneousDeductionFailure; if (isa(Args[ArgIdx])) { // C++0x [temp.deduct.type]p22: // If the original function parameter associated with A is a function // parameter pack and the function parameter associated with P is not // a function parameter pack, then template argument deduction fails. - return Sema::TDK_MiscellaneousDeductionFailure; + return TemplateDeductionResult::MiscellaneousDeductionFailure; } - if (Sema::TemplateDeductionResult Result = - DeduceTemplateArgumentsByTypeMatch( - S, TemplateParams, Params[ParamIdx].getUnqualifiedType(), - Args[ArgIdx].getUnqualifiedType(), Info, Deduced, TDF, - PartialOrdering, - /*DeducedFromArrayBound=*/false)) + if (TemplateDeductionResult Result = DeduceTemplateArgumentsByTypeMatch( + S, TemplateParams, Params[ParamIdx].getUnqualifiedType(), + Args[ArgIdx].getUnqualifiedType(), Info, Deduced, TDF, + PartialOrdering, + /*DeducedFromArrayBound=*/false); + Result != TemplateDeductionResult::Success) return Result; ++ArgIdx; @@ -1123,11 +1123,11 @@ DeduceTemplateArguments(Sema &S, if (ParamIdx + 1 == NumParams || PackScope.hasFixedArity()) { for (; ArgIdx < NumArgs && PackScope.hasNextElement(); ++ArgIdx) { // Deduce template arguments from the pattern. - if (Sema::TemplateDeductionResult Result = - DeduceTemplateArgumentsByTypeMatch( - S, TemplateParams, Pattern.getUnqualifiedType(), - Args[ArgIdx].getUnqualifiedType(), Info, Deduced, TDF, - PartialOrdering, /*DeducedFromArrayBound=*/false)) + if (TemplateDeductionResult Result = DeduceTemplateArgumentsByTypeMatch( + S, TemplateParams, Pattern.getUnqualifiedType(), + Args[ArgIdx].getUnqualifiedType(), Info, Deduced, TDF, + PartialOrdering, /*DeducedFromArrayBound=*/false); + Result != TemplateDeductionResult::Success) return Result; PackScope.nextPackElement(); @@ -1160,7 +1160,8 @@ DeduceTemplateArguments(Sema &S, // Build argument packs for each of the parameter packs expanded by this // pack expansion. - if (auto Result = PackScope.finish()) + if (auto Result = PackScope.finish(); + Result != TemplateDeductionResult::Success) return Result; } @@ -1172,13 +1173,13 @@ DeduceTemplateArguments(Sema &S, // Ai is ignored; if (PartialOrdering && ArgIdx + 1 == NumArgs && isa(Args[ArgIdx])) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; // Make sure we don't have any extra arguments. if (ArgIdx < NumArgs) - return Sema::TDK_MiscellaneousDeductionFailure; + return TemplateDeductionResult::MiscellaneousDeductionFailure; - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } /// Determine whether the parameter has qualifiers that the argument @@ -1286,7 +1287,7 @@ static CXXRecordDecl *getCanonicalRD(QualType T) { /// \returns the result of template argument deduction with the bases. "invalid" /// means no matches, "success" found a single item, and the /// "MiscellaneousDeductionFailure" result happens when the match is ambiguous. -static Sema::TemplateDeductionResult +static TemplateDeductionResult DeduceTemplateBases(Sema &S, const CXXRecordDecl *RD, TemplateParameterList *TemplateParams, QualType P, TemplateDeductionInfo &Info, @@ -1338,13 +1339,13 @@ DeduceTemplateBases(Sema &S, const CXXRecordDecl *RD, SmallVector DeducedCopy(Deduced.begin(), Deduced.end()); TemplateDeductionInfo BaseInfo(TemplateDeductionInfo::ForBase, Info); - Sema::TemplateDeductionResult BaseResult = DeduceTemplateSpecArguments( + TemplateDeductionResult BaseResult = DeduceTemplateSpecArguments( S, TemplateParams, P, NextT, BaseInfo, DeducedCopy); // If this was a successful deduction, add it to the list of matches, // otherwise we need to continue searching its bases. const CXXRecordDecl *RD = ::getCanonicalRD(NextT); - if (BaseResult == Sema::TDK_Success) + if (BaseResult == TemplateDeductionResult::Success) Matches.insert({RD, DeducedCopy}); else AddBases(RD); @@ -1374,12 +1375,12 @@ DeduceTemplateBases(Sema &S, const CXXRecordDecl *RD, } if (Matches.empty()) - return Sema::TDK_Invalid; + return TemplateDeductionResult::Invalid; if (Matches.size() > 1) - return Sema::TDK_MiscellaneousDeductionFailure; + return TemplateDeductionResult::MiscellaneousDeductionFailure; std::swap(Matches.front().second, Deduced); - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } /// Deduce the template arguments by comparing the parameter type and @@ -1406,7 +1407,7 @@ DeduceTemplateBases(Sema &S, const CXXRecordDecl *RD, /// \returns the result of template argument deduction so far. Note that a /// "success" result means that template argument deduction has not yet failed, /// but it may still fail, later, for other reasons. -static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( +static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( Sema &S, TemplateParameterList *TemplateParams, QualType P, QualType A, TemplateDeductionInfo &Info, SmallVectorImpl &Deduced, unsigned TDF, @@ -1460,7 +1461,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( PQuals.withoutObjCLifetime() == AQuals.withoutObjCLifetime())) { Info.FirstArg = TemplateArgument(P); Info.SecondArg = TemplateArgument(A); - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } } Qualifiers DiscardedQuals; @@ -1514,7 +1515,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( // Just skip any attempts to deduce from a placeholder type or a parameter // at a different depth. if (A->isPlaceholderType() || Info.getDeducedDepth() != TTP->getDepth()) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; unsigned Index = TTP->getIndex(); @@ -1534,13 +1535,13 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( Info.Param = cast(TemplateParams->getParam(Index)); Info.FirstArg = TemplateArgument(P); Info.SecondArg = TemplateArgument(A); - return Sema::TDK_Underqualified; + return TemplateDeductionResult::Underqualified; } // Do not match a function type with a cv-qualified type. // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1584 if (A->isFunctionType() && P.hasQualifiers()) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; assert(TTP->getDepth() == Info.getDeducedDepth() && "saw template type parameter with wrong depth"); @@ -1568,7 +1569,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( Info.Param = cast(TemplateParams->getParam(Index)); Info.FirstArg = TemplateArgument(P); Info.SecondArg = TemplateArgument(A); - return Sema::TDK_Underqualified; + return TemplateDeductionResult::Underqualified; } // Objective-C ARC: @@ -1588,11 +1589,11 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( Info.Param = cast(TemplateParams->getParam(Index)); Info.FirstArg = Deduced[Index]; Info.SecondArg = NewDeduced; - return Sema::TDK_Inconsistent; + return TemplateDeductionResult::Inconsistent; } Deduced[Index] = Result; - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } // Set up the template argument deduction information for a failure. @@ -1604,19 +1605,19 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( // at, so we have to wait until all of the parameter packs in this // expansion have arguments. if (P->getAs()) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; // Check the cv-qualifiers on the parameter and argument types. if (!(TDF & TDF_IgnoreQualifiers)) { if (TDF & TDF_ParamWithReferenceType) { if (hasInconsistentOrSupersetQualifiersOf(P, A)) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } else if (TDF & TDF_ArgWithReferenceType) { // C++ [temp.deduct.conv]p4: // If the original A is a reference type, A can be more cv-qualified // than the deduced A if (!A.getQualifiers().compatiblyIncludes(P.getQualifiers())) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; // Strip out all extra qualifiers from the argument to figure out the // type we're converting to, prior to the qualification conversion. @@ -1625,22 +1626,22 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( A = S.Context.getQualifiedType(A, P.getQualifiers()); } else if (!IsPossiblyOpaquelyQualifiedType(P)) { if (P.getCVRQualifiers() != A.getCVRQualifiers()) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } } // If the parameter type is not dependent, there is nothing to deduce. if (!P->isDependentType()) { if (TDF & TDF_SkipNonDependent) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; if ((TDF & TDF_IgnoreQualifiers) ? S.Context.hasSameUnqualifiedType(P, A) : S.Context.hasSameType(P, A)) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; if (TDF & TDF_AllowCompatibleFunctionType && S.isSameOrCompatibleFunctionType(P, A)) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; if (!(TDF & TDF_IgnoreQualifiers)) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; // Otherwise, when ignoring qualifiers, the types not having the same // unqualified type does not mean they do not match, so in this case we // must keep going and analyze with a non-dependent parameter type. @@ -1664,7 +1665,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( // There's no corresponding wording for [temp.deduct.decl], but we treat // it the same to match other compilers. if (P->isDependentType()) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; [[fallthrough]]; case Type::Builtin: case Type::VariableArray: @@ -1680,14 +1681,14 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( ((TDF & TDF_IgnoreQualifiers) ? S.Context.hasSameUnqualifiedType(P, A) : S.Context.hasSameType(P, A)) - ? Sema::TDK_Success - : Sema::TDK_NonDeducedMismatch; + ? TemplateDeductionResult::Success + : TemplateDeductionResult::NonDeducedMismatch; // _Complex T [placeholder extension] case Type::Complex: { const auto *CP = P->castAs(), *CA = A->getAs(); if (!CA) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; return DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, CP->getElementType(), CA->getElementType(), Info, Deduced, TDF); @@ -1697,7 +1698,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( case Type::Atomic: { const auto *PA = P->castAs(), *AA = A->getAs(); if (!AA) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; return DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, PA->getValueType(), AA->getValueType(), Info, Deduced, TDF); @@ -1711,7 +1712,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( } else if (const auto *PA = A->getAs()) { PointeeType = PA->getPointeeType(); } else { - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } return DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, P->castAs()->getPointeeType(), @@ -1724,7 +1725,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( const auto *RP = P->castAs(), *RA = A->getAs(); if (!RA) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; return DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, RP->getPointeeType(), RA->getPointeeType(), Info, @@ -1736,7 +1737,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( const auto *RP = P->castAs(), *RA = A->getAs(); if (!RA) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; return DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, RP->getPointeeType(), RA->getPointeeType(), Info, @@ -1747,7 +1748,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( case Type::IncompleteArray: { const auto *IAA = S.Context.getAsIncompleteArrayType(A); if (!IAA) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; const auto *IAP = S.Context.getAsIncompleteArrayType(P); assert(IAP && "Template parameter not of incomplete array type"); @@ -1763,7 +1764,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( *CAP = S.Context.getAsConstantArrayType(P); assert(CAP); if (!CAA || CAA->getSize() != CAP->getSize()) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; return DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, CAP->getElementType(), CAA->getElementType(), Info, @@ -1774,21 +1775,22 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( case Type::DependentSizedArray: { const auto *AA = S.Context.getAsArrayType(A); if (!AA) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; // Check the element type of the arrays const auto *DAP = S.Context.getAsDependentSizedArrayType(P); assert(DAP); if (auto Result = DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, DAP->getElementType(), AA->getElementType(), - Info, Deduced, TDF & TDF_IgnoreQualifiers)) + Info, Deduced, TDF & TDF_IgnoreQualifiers); + Result != TemplateDeductionResult::Success) return Result; // Determine the array bound is something we can deduce. const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(Info, DAP->getSizeExpr()); if (!NTTP) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; // We can perform template argument deduction for the given non-type // template parameter. @@ -1806,7 +1808,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, NTTP, DAA->getSizeExpr(), Info, Deduced); // Incomplete type does not match a dependently-sized array type - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } // type(*)(T) @@ -1816,30 +1818,32 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( const auto *FPP = P->castAs(), *FPA = A->getAs(); if (!FPA) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; if (FPP->getMethodQuals() != FPA->getMethodQuals() || FPP->getRefQualifier() != FPA->getRefQualifier() || FPP->isVariadic() != FPA->isVariadic()) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; // Check return types. if (auto Result = DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, FPP->getReturnType(), FPA->getReturnType(), Info, Deduced, 0, /*PartialOrdering=*/false, - /*DeducedFromArrayBound=*/false)) + /*DeducedFromArrayBound=*/false); + Result != TemplateDeductionResult::Success) return Result; // Check parameter types. if (auto Result = DeduceTemplateArguments( S, TemplateParams, FPP->param_type_begin(), FPP->getNumParams(), FPA->param_type_begin(), FPA->getNumParams(), Info, Deduced, - TDF & TDF_TopLevelParameterTypeList, PartialOrdering)) + TDF & TDF_TopLevelParameterTypeList, PartialOrdering); + Result != TemplateDeductionResult::Success) return Result; if (TDF & TDF_AllowCompatibleFunctionType) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; // FIXME: Per core-2016/10/1019 (no corresponding core issue yet), permit // deducing through the noexcept-specifier if it's part of the canonical @@ -1877,7 +1881,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( // Careful about [temp.deduct.call] and [temp.deduct.conv], which allow // top-level differences in noexcept-specifications. - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } case Type::InjectedClassName: @@ -1901,7 +1905,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( auto Result = DeduceTemplateSpecArguments(S, TemplateParams, P, A, Info, Deduced); - if (Result == Sema::TDK_Success) + if (Result == TemplateDeductionResult::Success) return Result; // We cannot inspect base classes as part of deduction when the type @@ -1916,7 +1920,8 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( // Check bases according to C++14 [temp.deduct.call] p4b3: auto BaseResult = DeduceTemplateBases(S, getCanonicalRD(A), TemplateParams, P, Info, Deduced); - return BaseResult != Sema::TDK_Invalid ? BaseResult : Result; + return BaseResult != TemplateDeductionResult::Invalid ? BaseResult + : Result; } // T type::* @@ -1932,7 +1937,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( const auto *MPP = P->castAs(), *MPA = A->getAs(); if (!MPA) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; QualType PPT = MPP->getPointeeType(); if (PPT->isFunctionType()) @@ -1945,7 +1950,8 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( unsigned SubTDF = TDF & TDF_IgnoreQualifiers; if (auto Result = DeduceTemplateArgumentsByTypeMatch( - S, TemplateParams, PPT, APT, Info, Deduced, SubTDF)) + S, TemplateParams, PPT, APT, Info, Deduced, SubTDF); + Result != TemplateDeductionResult::Success) return Result; return DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, QualType(MPP->getClass(), 0), @@ -1961,7 +1967,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( const auto *BPP = P->castAs(), *BPA = A->getAs(); if (!BPA) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; return DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, BPP->getPointeeType(), BPA->getPointeeType(), Info, Deduced, 0); @@ -1976,7 +1982,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( if (const auto *VA = A->getAs()) { // Make sure that the vectors have the same number of elements. if (VP->getNumElements() != VA->getNumElements()) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; ElementType = VA->getElementType(); } else if (const auto *VA = A->getAs()) { // We can't check the number of elements, since the argument has a @@ -1984,7 +1990,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( // ordering. ElementType = VA->getElementType(); } else { - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } // Perform deduction on the element types. return DeduceTemplateArgumentsByTypeMatch( @@ -1999,14 +2005,15 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( // Perform deduction on the element types. if (auto Result = DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, VP->getElementType(), VA->getElementType(), - Info, Deduced, TDF)) + Info, Deduced, TDF); + Result != TemplateDeductionResult::Success) return Result; // Perform deduction on the vector size, if we can. const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(Info, VP->getSizeExpr()); if (!NTTP) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false); ArgSize = VA->getNumElements(); @@ -2022,20 +2029,21 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( // Perform deduction on the element types. if (auto Result = DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, VP->getElementType(), VA->getElementType(), - Info, Deduced, TDF)) + Info, Deduced, TDF); + Result != TemplateDeductionResult::Success) return Result; // Perform deduction on the vector size, if we can. const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(Info, VP->getSizeExpr()); if (!NTTP) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, VA->getSizeExpr(), Info, Deduced); } - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } // (clang extension) @@ -2048,14 +2056,15 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( // Perform deduction on the element types. if (auto Result = DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, VP->getElementType(), VA->getElementType(), - Info, Deduced, TDF)) + Info, Deduced, TDF); + Result != TemplateDeductionResult::Success) return Result; // Perform deduction on the vector size, if we can. const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(Info, VP->getSizeExpr()); if (!NTTP) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false); ArgSize = VA->getNumElements(); @@ -2071,20 +2080,21 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( // Perform deduction on the element types. if (auto Result = DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, VP->getElementType(), VA->getElementType(), - Info, Deduced, TDF)) + Info, Deduced, TDF); + Result != TemplateDeductionResult::Success) return Result; // Perform deduction on the vector size, if we can. const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(Info, VP->getSizeExpr()); if (!NTTP) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, VA->getSizeExpr(), Info, Deduced); } - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } // (clang extension) @@ -2095,12 +2105,12 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( const auto *MP = P->castAs(), *MA = A->getAs(); if (!MA) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; // Check that the dimensions are the same if (MP->getNumRows() != MA->getNumRows() || MP->getNumColumns() != MA->getNumColumns()) { - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } // Perform deduction on element types. return DeduceTemplateArgumentsByTypeMatch( @@ -2112,12 +2122,13 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( const auto *MP = P->castAs(); const auto *MA = A->getAs(); if (!MA) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; // Check the element type of the matrixes. if (auto Result = DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, MP->getElementType(), MA->getElementType(), - Info, Deduced, TDF)) + Info, Deduced, TDF); + Result != TemplateDeductionResult::Success) return Result; // Try to deduce a matrix dimension. @@ -2132,26 +2143,26 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( std::optional ParamConst = ParamExpr->getIntegerConstantExpr(S.Context); if (!ParamConst) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; if (ACM) { if ((ACM->*GetArgDimension)() == *ParamConst) - return Sema::TDK_Success; - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::Success; + return TemplateDeductionResult::NonDeducedMismatch; } Expr *ArgExpr = (ADM->*GetArgDimensionExpr)(); if (std::optional ArgConst = ArgExpr->getIntegerConstantExpr(S.Context)) if (*ArgConst == *ParamConst) - return Sema::TDK_Success; - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::Success; + return TemplateDeductionResult::NonDeducedMismatch; } const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(Info, ParamExpr); if (!NTTP) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; if (ACM) { llvm::APSInt ArgConst( @@ -2169,7 +2180,8 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( if (auto Result = DeduceMatrixArg(MP->getRowExpr(), MA, &ConstantMatrixType::getNumRows, - &DependentSizedMatrixType::getRowExpr)) + &DependentSizedMatrixType::getRowExpr); + Result != TemplateDeductionResult::Success) return Result; return DeduceMatrixArg(MP->getColumnExpr(), MA, @@ -2187,14 +2199,15 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( // Perform deduction on the pointer type. if (auto Result = DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, ASP->getPointeeType(), ASA->getPointeeType(), - Info, Deduced, TDF)) + Info, Deduced, TDF); + Result != TemplateDeductionResult::Success) return Result; // Perform deduction on the address space, if we can. const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(Info, ASP->getAddrSpaceExpr()); if (!NTTP) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; return DeduceNonTypeTemplateArgument( S, TemplateParams, NTTP, ASA->getAddrSpaceExpr(), Info, Deduced); @@ -2208,33 +2221,34 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( // Perform deduction on the pointer types. if (auto Result = DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, ASP->getPointeeType(), - S.Context.removeAddrSpaceQualType(A), Info, Deduced, TDF)) + S.Context.removeAddrSpaceQualType(A), Info, Deduced, TDF); + Result != TemplateDeductionResult::Success) return Result; // Perform deduction on the address space, if we can. const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(Info, ASP->getAddrSpaceExpr()); if (!NTTP) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, ArgAddressSpace, S.Context.IntTy, true, Info, Deduced); } - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } case Type::DependentBitInt: { const auto *IP = P->castAs(); if (const auto *IA = A->getAs()) { if (IP->isUnsigned() != IA->isUnsigned()) - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; const NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(Info, IP->getNumBitsExpr()); if (!NTTP) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false); ArgSize = IA->getNumBits(); @@ -2246,11 +2260,11 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( if (const auto *IA = A->getAs()) { if (IP->isUnsigned() != IA->isUnsigned()) - return Sema::TDK_NonDeducedMismatch; - return Sema::TDK_Success; + return TemplateDeductionResult::NonDeducedMismatch; + return TemplateDeductionResult::Success; } - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } case Type::TypeOfExpr: @@ -2264,7 +2278,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( case Type::PackExpansion: case Type::Pipe: // No template argument deduction for these types - return Sema::TDK_Success; + return TemplateDeductionResult::Success; case Type::PackIndexing: { const PackIndexingType *PIT = P->getAs(); @@ -2272,14 +2286,14 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( return DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, PIT->getSelectedType(), A, Info, Deduced, TDF); } - return Sema::TDK_IncompletePack; + return TemplateDeductionResult::IncompletePack; } } llvm_unreachable("Invalid Type Class!"); } -static Sema::TemplateDeductionResult +static TemplateDeductionResult DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, const TemplateArgument &P, TemplateArgument A, TemplateDeductionInfo &Info, @@ -2300,7 +2314,7 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, S, TemplateParams, P.getAsType(), A.getAsType(), Info, Deduced, 0); Info.FirstArg = P; Info.SecondArg = A; - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; case TemplateArgument::Template: if (A.getKind() == TemplateArgument::Template) @@ -2308,7 +2322,7 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, A.getAsTemplate(), Info, Deduced); Info.FirstArg = P; Info.SecondArg = A; - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; case TemplateArgument::TemplateExpansion: llvm_unreachable("caller should handle pack expansions"); @@ -2316,38 +2330,38 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, case TemplateArgument::Declaration: if (A.getKind() == TemplateArgument::Declaration && isSameDeclaration(P.getAsDecl(), A.getAsDecl())) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; Info.FirstArg = P; Info.SecondArg = A; - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; case TemplateArgument::NullPtr: if (A.getKind() == TemplateArgument::NullPtr && S.Context.hasSameType(P.getNullPtrType(), A.getNullPtrType())) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; Info.FirstArg = P; Info.SecondArg = A; - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; case TemplateArgument::Integral: if (A.getKind() == TemplateArgument::Integral) { if (hasSameExtendedValue(P.getAsIntegral(), A.getAsIntegral())) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } Info.FirstArg = P; Info.SecondArg = A; - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; case TemplateArgument::StructuralValue: if (A.getKind() == TemplateArgument::StructuralValue && A.structurallyEquals(P)) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; Info.FirstArg = P; Info.SecondArg = A; - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; case TemplateArgument::Expression: if (const NonTypeTemplateParmDecl *NTTP = @@ -2376,13 +2390,13 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, case TemplateArgument::Pack: Info.FirstArg = P; Info.SecondArg = A; - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } llvm_unreachable("Unknown template argument kind"); } // Can't deduce anything, but that's okay. - return Sema::TDK_Success; + return TemplateDeductionResult::Success; case TemplateArgument::Pack: llvm_unreachable("Argument packs should be expanded by the caller!"); } @@ -2433,7 +2447,7 @@ static bool hasPackExpansionBeforeEnd(ArrayRef Args) { return false; } -static Sema::TemplateDeductionResult +static TemplateDeductionResult DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, ArrayRef Ps, ArrayRef As, @@ -2445,7 +2459,7 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, // the last template argument, the entire template argument list is a // non-deduced context. if (hasPackExpansionBeforeEnd(Ps)) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; // C++0x [temp.deduct.type]p9: // If P has a form that contains or , then each argument Pi of the @@ -2460,18 +2474,19 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, // Check whether we have enough arguments. if (!hasTemplateArgumentForDeduction(As, ArgIdx)) return NumberOfArgumentsMustMatch - ? Sema::TDK_MiscellaneousDeductionFailure - : Sema::TDK_Success; + ? TemplateDeductionResult::MiscellaneousDeductionFailure + : TemplateDeductionResult::Success; // C++1z [temp.deduct.type]p9: // During partial ordering, if Ai was originally a pack expansion [and] // Pi is not a pack expansion, template argument deduction fails. if (As[ArgIdx].isPackExpansion()) - return Sema::TDK_MiscellaneousDeductionFailure; + return TemplateDeductionResult::MiscellaneousDeductionFailure; // Perform deduction for this Pi/Ai pair. if (auto Result = DeduceTemplateArguments(S, TemplateParams, P, - As[ArgIdx], Info, Deduced)) + As[ArgIdx], Info, Deduced); + Result != TemplateDeductionResult::Success) return Result; // Move to the next argument. @@ -2499,7 +2514,8 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, ++ArgIdx) { // Deduce template arguments from the pattern. if (auto Result = DeduceTemplateArguments(S, TemplateParams, Pattern, - As[ArgIdx], Info, Deduced)) + As[ArgIdx], Info, Deduced); + Result != TemplateDeductionResult::Success) return Result; PackScope.nextPackElement(); @@ -2507,11 +2523,12 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, // Build argument packs for each of the parameter packs expanded by this // pack expansion. - if (auto Result = PackScope.finish()) + if (auto Result = PackScope.finish(); + Result != TemplateDeductionResult::Success) return Result; } - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } /// Determine whether two template arguments are the same. @@ -2773,7 +2790,7 @@ static bool ConvertDeducedTemplateArgument( // ClassTemplatePartialSpecializationDecl sadly does not derive from // TemplateDecl. template -static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments( +static TemplateDeductionResult ConvertDeducedTemplateArguments( Sema &S, TemplateDeclT *Template, bool IsDeduced, SmallVectorImpl &Deduced, TemplateDeductionInfo &Info, @@ -2792,7 +2809,8 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments( // FIXME: Where did the word "trailing" come from? if (Deduced[I].isNull() && Param->isTemplateParameterPack()) { if (auto Result = - PackDeductionScope(S, TemplateParams, Deduced, Info, I).finish()) + PackDeductionScope(S, TemplateParams, Deduced, Info, I).finish(); + Result != TemplateDeductionResult::Success) return Result; } @@ -2829,7 +2847,7 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments( Info.reset( TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder), TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder)); - return Sema::TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; } continue; @@ -2841,7 +2859,7 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments( if (!TD) { assert(isa(Template) || isa(Template)); - return Sema::TDK_Incomplete; + return TemplateDeductionResult::Incomplete; } TemplateArgumentLoc DefArg; @@ -2871,8 +2889,8 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments( TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder)); if (PartialOverloading) break; - return HasDefaultArg ? Sema::TDK_SubstitutionFailure - : Sema::TDK_Incomplete; + return HasDefaultArg ? TemplateDeductionResult::SubstitutionFailure + : TemplateDeductionResult::Incomplete; } // Check whether we can actually use the default argument. @@ -2884,13 +2902,13 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments( // FIXME: These template arguments are temporary. Free them! Info.reset(TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder), TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder)); - return Sema::TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; } // If we get here, we successfully used the default template argument. } - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } static DeclContext *getAsDeclContextOrEnclosing(Decl *D) { @@ -2926,7 +2944,7 @@ bool DeducedArgsNeedReplacement( } template -static Sema::TemplateDeductionResult +static TemplateDeductionResult CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template, ArrayRef SugaredDeducedArgs, ArrayRef CanonicalDeducedArgs, @@ -2959,15 +2977,15 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template, Info.reset( TemplateArgumentList::CreateCopy(S.Context, SugaredDeducedArgs), TemplateArgumentList::CreateCopy(S.Context, CanonicalDeducedArgs)); - return Sema::TDK_ConstraintsNotSatisfied; + return TemplateDeductionResult::ConstraintsNotSatisfied; } - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } /// Complete template argument deduction for a partial specialization. template static std::enable_if_t::value, - Sema::TemplateDeductionResult> + TemplateDeductionResult> FinishTemplateArgumentDeduction( Sema &S, T *Partial, bool IsPartialOrdering, ArrayRef TemplateArgs, @@ -2986,7 +3004,8 @@ FinishTemplateArgumentDeduction( SmallVector SugaredBuilder, CanonicalBuilder; if (auto Result = ConvertDeducedTemplateArguments( S, Partial, IsPartialOrdering, Deduced, Info, SugaredBuilder, - CanonicalBuilder)) + CanonicalBuilder); + Result != TemplateDeductionResult::Success) return Result; // Form the template argument list from the deduced template arguments. @@ -3023,7 +3042,7 @@ FinishTemplateArgumentDeduction( Partial->getTemplateParameters()->getParam(ParamIdx)); Info.Param = makeTemplateParameter(Param); Info.FirstArg = (*PartialTemplArgInfo)[ArgIdx].getArgument(); - return Sema::TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; } bool ConstraintsNotSatisfied; @@ -3033,8 +3052,9 @@ FinishTemplateArgumentDeduction( Template, Partial->getLocation(), InstArgs, false, SugaredConvertedInstArgs, CanonicalConvertedInstArgs, /*UpdateArgsWithConversions=*/true, &ConstraintsNotSatisfied)) - return ConstraintsNotSatisfied ? Sema::TDK_ConstraintsNotSatisfied - : Sema::TDK_SubstitutionFailure; + return ConstraintsNotSatisfied + ? TemplateDeductionResult::ConstraintsNotSatisfied + : TemplateDeductionResult::SubstitutionFailure; TemplateParameterList *TemplateParams = Template->getTemplateParameters(); for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) { @@ -3044,24 +3064,25 @@ FinishTemplateArgumentDeduction( Info.Param = makeTemplateParameter(TemplateParams->getParam(I)); Info.FirstArg = TemplateArgs[I]; Info.SecondArg = InstArg; - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } } if (Trap.hasErrorOccurred()) - return Sema::TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; if (auto Result = CheckDeducedArgumentConstraints(S, Partial, SugaredBuilder, - CanonicalBuilder, Info)) + CanonicalBuilder, Info); + Result != TemplateDeductionResult::Success) return Result; - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } /// Complete template argument deduction for a class or variable template, /// when partial ordering against a partial specialization. // FIXME: Factor out duplication with partial specialization version above. -static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction( +static TemplateDeductionResult FinishTemplateArgumentDeduction( Sema &S, TemplateDecl *Template, bool PartialOrdering, ArrayRef TemplateArgs, SmallVectorImpl &Deduced, @@ -3081,7 +3102,8 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction( S, Template, /*IsDeduced*/ PartialOrdering, Deduced, Info, SugaredBuilder, CanonicalBuilder, /*CurrentInstantiationScope=*/nullptr, - /*NumAlreadyConverted=*/0U, /*PartialOverloading=*/false)) + /*NumAlreadyConverted=*/0U, /*PartialOverloading=*/false); + Result != TemplateDeductionResult::Success) return Result; // Check that we produced the correct argument list. @@ -3093,29 +3115,30 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction( Info.Param = makeTemplateParameter(TemplateParams->getParam(I)); Info.FirstArg = TemplateArgs[I]; Info.SecondArg = InstArg; - return Sema::TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } } if (Trap.hasErrorOccurred()) - return Sema::TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; if (auto Result = CheckDeducedArgumentConstraints(S, Template, SugaredBuilder, - CanonicalBuilder, Info)) + CanonicalBuilder, Info); + Result != TemplateDeductionResult::Success) return Result; - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } /// Perform template argument deduction to determine whether /// the given template arguments match the given class template /// partial specialization per C++ [temp.class.spec.match]. -Sema::TemplateDeductionResult +TemplateDeductionResult Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, ArrayRef TemplateArgs, TemplateDeductionInfo &Info) { if (Partial->isInvalidDecl()) - return TDK_Invalid; + return TemplateDeductionResult::Invalid; // C++ [temp.class.spec.match]p2: // A partial specialization matches a given actual template @@ -3137,17 +3160,18 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, if (TemplateDeductionResult Result = ::DeduceTemplateArguments( *this, Partial->getTemplateParameters(), Partial->getTemplateArgs().asArray(), TemplateArgs, Info, Deduced, - /*NumberOfArgumentsMustMatch=*/false)) + /*NumberOfArgumentsMustMatch=*/false); + Result != TemplateDeductionResult::Success) return Result; SmallVector DeducedArgs(Deduced.begin(), Deduced.end()); InstantiatingTemplate Inst(*this, Info.getLocation(), Partial, DeducedArgs, Info); if (Inst.isInvalid()) - return TDK_InstantiationDepth; + return TemplateDeductionResult::InstantiationDepth; if (Trap.hasErrorOccurred()) - return Sema::TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; TemplateDeductionResult Result; runWithSufficientStackSpace(Info.getLocation(), [&] { @@ -3161,12 +3185,12 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, /// Perform template argument deduction to determine whether /// the given template arguments match the given variable template /// partial specialization per C++ [temp.class.spec.match]. -Sema::TemplateDeductionResult +TemplateDeductionResult Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial, ArrayRef TemplateArgs, TemplateDeductionInfo &Info) { if (Partial->isInvalidDecl()) - return TDK_Invalid; + return TemplateDeductionResult::Invalid; // C++ [temp.class.spec.match]p2: // A partial specialization matches a given actual template @@ -3188,17 +3212,18 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial, if (TemplateDeductionResult Result = ::DeduceTemplateArguments( *this, Partial->getTemplateParameters(), Partial->getTemplateArgs().asArray(), TemplateArgs, Info, Deduced, - /*NumberOfArgumentsMustMatch=*/false)) + /*NumberOfArgumentsMustMatch=*/false); + Result != TemplateDeductionResult::Success) return Result; SmallVector DeducedArgs(Deduced.begin(), Deduced.end()); InstantiatingTemplate Inst(*this, Info.getLocation(), Partial, DeducedArgs, Info); if (Inst.isInvalid()) - return TDK_InstantiationDepth; + return TemplateDeductionResult::InstantiationDepth; if (Trap.hasErrorOccurred()) - return Sema::TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; TemplateDeductionResult Result; runWithSufficientStackSpace(Info.getLocation(), [&] { @@ -3251,9 +3276,9 @@ static bool isSimpleTemplateIdType(QualType T) { /// \param Info if substitution fails for any reason, this object will be /// populated with more information about the failure. /// -/// \returns TDK_Success if substitution was successful, or some failure -/// condition. -Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( +/// \returns TemplateDeductionResult::Success if substitution was successful, or +/// some failure condition. +TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo &ExplicitTemplateArgs, SmallVectorImpl &Deduced, @@ -3271,7 +3296,7 @@ Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( if (FunctionType) *FunctionType = Function->getType(); - return TDK_Success; + return TemplateDeductionResult::Success; } // Unevaluated SFINAE context. @@ -3294,7 +3319,7 @@ Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( *this, Info.getLocation(), FunctionTemplate, DeducedArgs, CodeSynthesisContext::ExplicitTemplateArgumentSubstitution, Info); if (Inst.isInvalid()) - return TDK_InstantiationDepth; + return TemplateDeductionResult::InstantiationDepth; if (CheckTemplateArgumentList(FunctionTemplate, SourceLocation(), ExplicitTemplateArgs, true, SugaredBuilder, @@ -3303,9 +3328,9 @@ Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( Trap.hasErrorOccurred()) { unsigned Index = SugaredBuilder.size(); if (Index >= TemplateParams->size()) - return TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; Info.Param = makeTemplateParameter(TemplateParams->getParam(Index)); - return TDK_InvalidExplicitArguments; + return TemplateDeductionResult::InvalidExplicitArguments; } // Form the template argument list from the explicitly-specified @@ -3364,7 +3389,7 @@ Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( if (SubstParmTypes(Function->getLocation(), Function->parameters(), Proto->getExtParameterInfosOrNull(), MLTAL, ParamTypes, /*params=*/nullptr, ExtParamInfos)) - return TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; } // Instantiate the return type. @@ -3390,13 +3415,13 @@ Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( SubstType(Proto->getReturnType(), MLTAL, Function->getTypeSpecStartLoc(), Function->getDeclName()); if (ResultType.isNull() || Trap.hasErrorOccurred()) - return TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; // CUDA: Kernel function must have 'void' return type. if (getLangOpts().CUDA) if (Function->hasAttr() && !ResultType->isVoidType()) { Diag(Function->getLocation(), diag::err_kern_type_not_void_return) << Function->getType() << Function->getSourceRange(); - return TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; } } @@ -3406,7 +3431,7 @@ Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( SubstParmTypes(Function->getLocation(), Function->parameters(), Proto->getExtParameterInfosOrNull(), MLTAL, ParamTypes, /*params*/ nullptr, ExtParamInfos)) - return TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; if (FunctionType) { auto EPI = Proto->getExtProtoInfo(); @@ -3426,14 +3451,14 @@ Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/false, /*SkipForSpecialization=*/true))) - return TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; *FunctionType = BuildFunctionType(ResultType, ParamTypes, Function->getLocation(), Function->getDeclName(), EPI); if (FunctionType->isNull() || Trap.hasErrorOccurred()) - return TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; } // C++ [temp.arg.explicit]p2: @@ -3455,23 +3480,24 @@ Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( Deduced.push_back(Arg); } - return TDK_Success; + return TemplateDeductionResult::Success; } /// Check whether the deduced argument type for a call to a function /// template matches the actual argument type per C++ [temp.deduct.call]p4. -static Sema::TemplateDeductionResult +static TemplateDeductionResult CheckOriginalCallArgDeduction(Sema &S, TemplateDeductionInfo &Info, Sema::OriginalCallArg OriginalArg, QualType DeducedA) { ASTContext &Context = S.Context; - auto Failed = [&]() -> Sema::TemplateDeductionResult { + auto Failed = [&]() -> TemplateDeductionResult { Info.FirstArg = TemplateArgument(DeducedA); Info.SecondArg = TemplateArgument(OriginalArg.OriginalArgType); Info.CallArgIndex = OriginalArg.ArgIdx; - return OriginalArg.DecomposedParam ? Sema::TDK_DeducedMismatchNested - : Sema::TDK_DeducedMismatch; + return OriginalArg.DecomposedParam + ? TemplateDeductionResult::DeducedMismatchNested + : TemplateDeductionResult::DeducedMismatch; }; QualType A = OriginalArg.OriginalArgType; @@ -3479,7 +3505,7 @@ CheckOriginalCallArgDeduction(Sema &S, TemplateDeductionInfo &Info, // Check for type equality (top-level cv-qualifiers are ignored). if (Context.hasSameUnqualifiedType(A, DeducedA)) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; // Strip off references on the argument types; they aren't needed for // the following checks. @@ -3503,7 +3529,7 @@ CheckOriginalCallArgDeduction(Sema &S, TemplateDeductionInfo &Info, // the deduced A can be F. QualType Tmp; if (A->isFunctionType() && S.IsFunctionConversion(A, DeducedA, Tmp)) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; Qualifiers AQuals = A.getQualifiers(); Qualifiers DeducedAQuals = DeducedA.getQualifiers(); @@ -3544,7 +3570,7 @@ CheckOriginalCallArgDeduction(Sema &S, TemplateDeductionInfo &Info, (S.IsQualificationConversion(A, DeducedA, false, ObjCLifetimeConversion) || S.IsFunctionConversion(A, DeducedA, ResultTy))) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; // - If P is a class and P has the form simple-template-id, then the // transformed A can be a derived class of the deduced A. [...] @@ -3565,11 +3591,11 @@ CheckOriginalCallArgDeduction(Sema &S, TemplateDeductionInfo &Info, } if (Context.hasSameUnqualifiedType(A, DeducedA)) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; if (A->isRecordType() && isSimpleTemplateIdType(OriginalParamType) && S.IsDerivedFrom(Info.getLocation(), A, DeducedA)) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; return Failed(); } @@ -3607,7 +3633,7 @@ static unsigned getPackIndexForParam(Sema &S, // if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`, // we'll try to instantiate and update its explicit specifier after constraint // checking. -static Sema::TemplateDeductionResult instantiateExplicitSpecifierDeferred( +static TemplateDeductionResult instantiateExplicitSpecifierDeferred( Sema &S, FunctionDecl *Specialization, const MultiLevelTemplateArgumentList &SubstArgs, TemplateDeductionInfo &Info, FunctionTemplateDecl *FunctionTemplate, @@ -3626,24 +3652,24 @@ static Sema::TemplateDeductionResult instantiateExplicitSpecifierDeferred( ExplicitSpecifier ES = GetExplicitSpecifier(Specialization); Expr *ExplicitExpr = ES.getExpr(); if (!ExplicitExpr) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; if (!ExplicitExpr->isValueDependent()) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; Sema::InstantiatingTemplate Inst( S, Info.getLocation(), FunctionTemplate, DeducedArgs, Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info); if (Inst.isInvalid()) - return Sema::TDK_InstantiationDepth; + return TemplateDeductionResult::InstantiationDepth; Sema::SFINAETrap Trap(S); const ExplicitSpecifier InstantiatedES = S.instantiateExplicitSpecifier(SubstArgs, ES); if (InstantiatedES.isInvalid() || Trap.hasErrorOccurred()) { Specialization->setInvalidDecl(true); - return Sema::TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; } SetExplicitSpecifier(Specialization, InstantiatedES); - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } /// Finish template argument deduction for a function template, @@ -3652,7 +3678,7 @@ static Sema::TemplateDeductionResult instantiateExplicitSpecifierDeferred( /// /// \param OriginalCallArgs If non-NULL, the original call arguments against /// which the deduced argument types should be compared. -Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( +TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( FunctionTemplateDecl *FunctionTemplate, SmallVectorImpl &Deduced, unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, @@ -3671,7 +3697,7 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( *this, Info.getLocation(), FunctionTemplate, DeducedArgs, CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info); if (Inst.isInvalid()) - return TDK_InstantiationDepth; + return TemplateDeductionResult::InstantiationDepth; ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl()); @@ -3682,7 +3708,8 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( if (auto Result = ConvertDeducedTemplateArguments( *this, FunctionTemplate, /*IsDeduced*/ true, Deduced, Info, SugaredBuilder, CanonicalBuilder, CurrentInstantiationScope, - NumExplicitlySpecified, PartialOverloading)) + NumExplicitlySpecified, PartialOverloading); + Result != TemplateDeductionResult::Success) return Result; // C++ [temp.deduct.call]p10: [DR1391] @@ -3695,7 +3722,7 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( // explicitly-specified template arguments, if the corresponding argument // A cannot be implicitly converted to P, deduction fails. if (CheckNonDependent()) - return TDK_NonDependentConversionFailure; + return TemplateDeductionResult::NonDependentConversionFailure; // Form the template argument list from the deduced template arguments. TemplateArgumentList *SugaredDeducedArgumentList = @@ -3732,7 +3759,7 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( Specialization = cast_or_null( SubstDecl(FD, Owner, SubstArgs)); if (!Specialization || Specialization->isInvalidDecl()) - return TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; assert(Specialization->getPrimaryTemplate()->getCanonicalDecl() == FunctionTemplate->getCanonicalDecl()); @@ -3749,7 +3776,7 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( // failure. if (Trap.hasErrorOccurred()) { Specialization->setInvalidDecl(true); - return TDK_SubstitutionFailure; + return TemplateDeductionResult::SubstitutionFailure; } // C++2a [temp.deduct]p5 @@ -3766,12 +3793,12 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( if (CheckInstantiatedFunctionTemplateConstraints( Info.getLocation(), Specialization, CanonicalBuilder, Info.AssociatedConstraintsSatisfaction)) - return TDK_MiscellaneousDeductionFailure; + return TemplateDeductionResult::MiscellaneousDeductionFailure; if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) { Info.reset(Info.takeSugared(), TemplateArgumentList::CreateCopy(Context, CanonicalBuilder)); - return TDK_ConstraintsNotSatisfied; + return TemplateDeductionResult::ConstraintsNotSatisfied; } } @@ -3779,10 +3806,11 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( // substitution of `FD` before. So, we try to instantiate it back if // `Specialization` is either a constructor or a conversion function. if (isa(Specialization)) { - if (TDK_Success != instantiateExplicitSpecifierDeferred( - *this, Specialization, SubstArgs, Info, - FunctionTemplate, DeducedArgs)) { - return TDK_SubstitutionFailure; + if (TemplateDeductionResult::Success != + instantiateExplicitSpecifierDeferred(*this, Specialization, SubstArgs, + Info, FunctionTemplate, + DeducedArgs)) { + return TemplateDeductionResult::SubstitutionFailure; } } @@ -3829,7 +3857,8 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( } if (auto TDK = - CheckOriginalCallArgDeduction(*this, Info, OriginalArg, DeducedA)) + CheckOriginalCallArgDeduction(*this, Info, OriginalArg, DeducedA); + TDK != TemplateDeductionResult::Success) return TDK; } } @@ -3846,7 +3875,7 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( .append(Info.diag_begin(), Info.diag_end()); } - return TDK_Success; + return TemplateDeductionResult::Success; } /// Gets the type of a function for template-argument-deducton @@ -3938,7 +3967,8 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, FunctionDecl *Specialization = nullptr; TemplateDeductionInfo Info(Ovl->getNameLoc()); if (S.DeduceTemplateArguments(FunTmpl, &ExplicitTemplateArgs, - Specialization, Info)) + Specialization, + Info) != TemplateDeductionResult::Success) continue; D = Specialization; @@ -3968,10 +3998,10 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, SmallVector Deduced(TemplateParams->size()); TemplateDeductionInfo Info(Ovl->getNameLoc()); - Sema::TemplateDeductionResult Result - = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType, - ArgType, Info, Deduced, TDF); - if (Result) continue; + TemplateDeductionResult Result = DeduceTemplateArgumentsByTypeMatch( + S, TemplateParams, ParamType, ArgType, Info, Deduced, TDF); + if (Result != TemplateDeductionResult::Success) + continue; if (!Match.isNull()) return {}; Match = ArgType; @@ -4084,7 +4114,7 @@ static bool hasDeducibleTemplateParameters(Sema &S, FunctionTemplateDecl *FunctionTemplate, QualType T); -static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( +static TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, QualType ParamType, QualType ArgType, Expr::Classification ArgClassification, Expr *Arg, @@ -4096,7 +4126,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( /// Attempt template argument deduction from an initializer list /// deemed to be an argument in a function call. -static Sema::TemplateDeductionResult DeduceFromInitializerList( +static TemplateDeductionResult DeduceFromInitializerList( Sema &S, TemplateParameterList *TemplateParams, QualType AdjustedParamType, InitListExpr *ILE, TemplateDeductionInfo &Info, SmallVectorImpl &Deduced, @@ -4111,7 +4141,7 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList( // // We've already removed references and cv-qualifiers here. if (!ILE->getNumInits()) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; QualType ElTy; auto *ArrTy = S.Context.getAsArrayType(AdjustedParamType); @@ -4120,14 +4150,14 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList( else if (!S.isStdInitializerList(AdjustedParamType, &ElTy)) { // Otherwise, an initializer list argument causes the parameter to be // considered a non-deduced context - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } // Resolving a core issue: a braced-init-list containing any designators is // a non-deduced context. for (Expr *E : ILE->inits()) if (isa(E)) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; // Deduction only needs to be done for dependent types. if (ElTy->isDependentType()) { @@ -4135,7 +4165,8 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList( if (auto Result = DeduceTemplateArgumentsFromCallArgument( S, TemplateParams, 0, ElTy, E->getType(), E->Classify(S.getASTContext()), E, Info, Deduced, - OriginalCallArgs, true, ArgIdx, TDF)) + OriginalCallArgs, true, ArgIdx, TDF); + Result != TemplateDeductionResult::Success) return Result; } } @@ -4154,17 +4185,18 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList( llvm::APInt Size(S.Context.getIntWidth(T), ILE->getNumInits()); if (auto Result = DeduceNonTypeTemplateArgument( S, TemplateParams, NTTP, llvm::APSInt(Size), T, - /*ArrayBound=*/true, Info, Deduced)) + /*ArrayBound=*/true, Info, Deduced); + Result != TemplateDeductionResult::Success) return Result; } } - return Sema::TDK_Success; + return TemplateDeductionResult::Success; } /// Perform template argument deduction per [temp.deduct.call] for a /// single parameter / argument pair. -static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( +static TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, QualType ParamType, QualType ArgType, Expr::Classification ArgClassification, Expr *Arg, @@ -4181,7 +4213,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( if (AdjustFunctionParmAndArgTypesForDeduction( S, TemplateParams, FirstInnerIndex, ParamType, ArgType, ArgClassification, Arg, TDF, FailedTSC)) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; // If [...] the argument is a non-empty initializer list [...] if (InitListExpr *ILE = dyn_cast_if_present(Arg)) @@ -4221,11 +4253,11 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( /// \param CheckNonDependent A callback to invoke to check conversions for /// non-dependent parameters, between deduction and substitution, per DR1391. /// If this returns true, substitution will be skipped and we return -/// TDK_NonDependentConversionFailure. The callback is passed the parameter -/// types (after substituting explicit template arguments). +/// TemplateDeductionResult::NonDependentConversionFailure. The callback is +/// passed the parameter types (after substituting explicit template arguments). /// /// \returns the result of template argument deduction. -Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( +TemplateDeductionResult Sema::DeduceTemplateArguments( FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args, FunctionDecl *&Specialization, TemplateDeductionInfo &Info, @@ -4233,7 +4265,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( QualType ObjectType, Expr::Classification ObjectClassification, llvm::function_ref)> CheckNonDependent) { if (FunctionTemplate->isInvalidDecl()) - return TDK_Invalid; + return TemplateDeductionResult::Invalid; FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); unsigned NumParams = Function->getNumParams(); @@ -4252,14 +4284,14 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // of the call (call it A) as described below. if (Args.size() < Function->getMinRequiredExplicitArguments() && !PartialOverloading) - return TDK_TooFewArguments; + return TemplateDeductionResult::TooFewArguments; else if (TooManyArguments(NumParams, Args.size() + ExplicitObjectOffset, PartialOverloading)) { const auto *Proto = Function->getType()->castAs(); if (Proto->isTemplateVariadic()) /* Do nothing */; else if (!Proto->isVariadic()) - return TDK_TooManyArguments; + return TemplateDeductionResult::TooManyArguments; } // The types of the parameters from which we will perform template argument @@ -4277,7 +4309,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( FunctionTemplate, *ExplicitTemplateArgs, Deduced, ParamTypes, nullptr, Info); }); - if (Result) + if (Result != TemplateDeductionResult::Success) return Result; NumExplicitlySpecified = Deduced.size(); @@ -4297,7 +4329,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // parameter that contains template-parameters that participate in // template argument deduction ... if (!hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType)) - return Sema::TDK_Success; + return TemplateDeductionResult::Success; if (ExplicitObjetArgument) { // ... with the type of the corresponding argument @@ -4334,13 +4366,15 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( if (ParamIdx == 0 && HasExplicitObject) { if (auto Result = DeduceCallArgument(ParamType, 0, - /*ExplicitObjetArgument=*/true)) + /*ExplicitObjetArgument=*/true); + Result != TemplateDeductionResult::Success) return Result; continue; } if (auto Result = DeduceCallArgument(ParamType, ArgIdx++, - /*ExplicitObjetArgument=*/false)) + /*ExplicitObjetArgument=*/false); + Result != TemplateDeductionResult::Success) return Result; continue; @@ -4374,7 +4408,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( PackScope.nextPackElement(), ++ArgIdx) { ParamTypesForArgChecking.push_back(ParamPattern); if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx, - /*ExplicitObjetArgument=*/false)) + /*ExplicitObjetArgument=*/false); + Result != TemplateDeductionResult::Success) return Result; } } else { @@ -4414,7 +4449,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( for (; ArgIdx < PackArgEnd && ArgIdx < Args.size(); ArgIdx++) { ParamTypesForArgChecking.push_back(ParamPattern); if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx, - /*ExplicitObjetArgument=*/false)) + /*ExplicitObjetArgument=*/false); + Result != TemplateDeductionResult::Success) return Result; PackScope.nextPackElement(); @@ -4424,7 +4460,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // Build argument packs for each of the parameter packs expanded by this // pack expansion. - if (auto Result = PackScope.finish()) + if (auto Result = PackScope.finish(); + Result != TemplateDeductionResult::Success) return Result; } @@ -4508,13 +4545,13 @@ QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType, /// specialization based on its signature, per [temp.deduct.decl]. /// /// \returns the result of template argument deduction. -Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( +TemplateDeductionResult Sema::DeduceTemplateArguments( FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType, FunctionDecl *&Specialization, TemplateDeductionInfo &Info, bool IsAddressOfFunction) { if (FunctionTemplate->isInvalidDecl()) - return TDK_Invalid; + return TemplateDeductionResult::Invalid; FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); TemplateParameterList *TemplateParams @@ -4533,7 +4570,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( FunctionTemplate, *ExplicitTemplateArgs, Deduced, ParamTypes, &FunctionType, Info); }); - if (Result) + if (Result != TemplateDeductionResult::Success) return Result; NumExplicitlySpecified = Deduced.size(); @@ -4566,10 +4603,10 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( unsigned TDF = TDF_TopLevelParameterTypeList | TDF_AllowCompatibleFunctionType; // Deduce template arguments from the function type. - if (TemplateDeductionResult Result - = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, - FunctionType, ArgFunctionType, - Info, Deduced, TDF)) + if (TemplateDeductionResult Result = DeduceTemplateArgumentsByTypeMatch( + *this, TemplateParams, FunctionType, ArgFunctionType, Info, Deduced, + TDF); + Result != TemplateDeductionResult::Success) return Result; } @@ -4579,7 +4616,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( NumExplicitlySpecified, Specialization, Info); }); - if (Result) + if (Result != TemplateDeductionResult::Success) return Result; // If the function has a deduced return type, deduce it now, so we can check @@ -4587,13 +4624,13 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( if (HasDeducedReturnType && IsAddressOfFunction && Specialization->getReturnType()->isUndeducedType() && DeduceReturnType(Specialization, Info.getLocation(), false)) - return TDK_MiscellaneousDeductionFailure; + return TemplateDeductionResult::MiscellaneousDeductionFailure; if (IsAddressOfFunction && getLangOpts().CPlusPlus20 && Specialization->isImmediateEscalating() && CheckIfFunctionSpecializationIsImmediate(Specialization, Info.getLocation())) - return TDK_MiscellaneousDeductionFailure; + return TemplateDeductionResult::MiscellaneousDeductionFailure; // If the function has a dependent exception specification, resolve it now, // so we can check that the exception specification matches. @@ -4602,7 +4639,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( if (getLangOpts().CPlusPlus17 && isUnresolvedExceptionSpec(SpecializationFPT->getExceptionSpecType()) && !ResolveExceptionSpec(Info.getLocation(), SpecializationFPT)) - return TDK_MiscellaneousDeductionFailure; + return TemplateDeductionResult::MiscellaneousDeductionFailure; // Adjust the exception specification of the argument to match the // substituted and resolved type we just formed. (Calling convention and @@ -4632,22 +4669,22 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( : !Context.hasSameType(SpecializationType, ArgFunctionType)) { Info.FirstArg = TemplateArgument(SpecializationType); Info.SecondArg = TemplateArgument(ArgFunctionType); - return TDK_NonDeducedMismatch; + return TemplateDeductionResult::NonDeducedMismatch; } } - return TDK_Success; + return TemplateDeductionResult::Success; } /// Deduce template arguments for a templated conversion /// function (C++ [temp.deduct.conv]) and, if successful, produce a /// conversion function template specialization. -Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( +TemplateDeductionResult Sema::DeduceTemplateArguments( FunctionTemplateDecl *ConversionTemplate, QualType ObjectType, Expr::Classification ObjectClassification, QualType ToType, CXXConversionDecl *&Specialization, TemplateDeductionInfo &Info) { if (ConversionTemplate->isInvalidDecl()) - return TDK_Invalid; + return TemplateDeductionResult::Invalid; CXXConversionDecl *ConversionGeneric = cast(ConversionTemplate->getTemplatedDecl()); @@ -4749,13 +4786,14 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( *this, TemplateParams, getFirstInnerIndex(ConversionTemplate), ParamType, ObjectType, ObjectClassification, /*Arg=*/nullptr, Info, Deduced, OriginalCallArgs, - /*Decomposed*/ false, 0, /*TDF*/ 0)) + /*Decomposed*/ false, 0, /*TDF*/ 0); + Result != TemplateDeductionResult::Success) return Result; } - if (TemplateDeductionResult Result - = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, - P, A, Info, Deduced, TDF)) + if (TemplateDeductionResult Result = DeduceTemplateArgumentsByTypeMatch( + *this, TemplateParams, P, A, Info, Deduced, TDF); + Result != TemplateDeductionResult::Success) return Result; // Create an Instantiation Scope for finalizing the operator. @@ -4796,11 +4834,12 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( /// naming a function template specialization. /// /// \returns the result of template argument deduction. -Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( - FunctionTemplateDecl *FunctionTemplate, - TemplateArgumentListInfo *ExplicitTemplateArgs, - FunctionDecl *&Specialization, TemplateDeductionInfo &Info, - bool IsAddressOfFunction) { +TemplateDeductionResult +Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + TemplateArgumentListInfo *ExplicitTemplateArgs, + FunctionDecl *&Specialization, + TemplateDeductionInfo &Info, + bool IsAddressOfFunction) { return DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, QualType(), Specialization, Info, IsAddressOfFunction); @@ -4962,14 +5001,14 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type, /// should be specified in the 'Info' parameter. /// \param IgnoreConstraints Set if we should not fail if the deduced type does /// not satisfy the type-constraint in the auto type. -Sema::TemplateDeductionResult +TemplateDeductionResult Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, TemplateDeductionInfo &Info, bool DependentDeduction, bool IgnoreConstraints, TemplateSpecCandidateSet *FailedTSC) { assert(DependentDeduction || Info.getDeducedDepth() == 0); if (Init->containsErrors()) - return TDK_AlreadyDiagnosed; + return TemplateDeductionResult::AlreadyDiagnosed; const AutoType *AT = Type.getType()->getContainedAutoType(); assert(AT); @@ -4977,7 +5016,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, if (Init->getType()->isNonOverloadPlaceholderType() || AT->isDecltypeAuto()) { ExprResult NonPlaceholder = CheckPlaceholderExpr(Init); if (NonPlaceholder.isInvalid()) - return TDK_AlreadyDiagnosed; + return TemplateDeductionResult::AlreadyDiagnosed; Init = NonPlaceholder.get(); } @@ -4989,7 +5028,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, Init->containsUnexpandedParameterPack())) { Result = SubstituteDeducedTypeTransform(*this, DependentResult).Apply(Type); assert(!Result.isNull() && "substituting DependentTy can't fail"); - return TDK_Success; + return TemplateDeductionResult::Success; } // Make sure that we treat 'char[]' equaly as 'char*' in C23 mode. @@ -4999,7 +5038,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, TypeLoc TL = TypeLoc(Init->getType(), Type.getOpaqueData()); Result = SubstituteDeducedTypeTransform(*this, DependentResult).Apply(TL); assert(!Result.isNull() && "substituting DependentTy can't fail"); - return TDK_Success; + return TemplateDeductionResult::Success; } // Emit a warning if 'auto*' is used in pedantic and in C23 mode. @@ -5011,7 +5050,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, if (!getLangOpts().CPlusPlus && InitList) { Diag(Init->getBeginLoc(), diag::err_auto_init_list_from_c) << (int)AT->getKeyword() << getLangOpts().C23; - return TDK_AlreadyDiagnosed; + return TemplateDeductionResult::AlreadyDiagnosed; } // Deduce type of TemplParam in Func(Init) @@ -5025,7 +5064,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, Result = SubstituteDeducedTypeTransform(*this, DependentResult).Apply(Type); assert(!Result.isNull() && "substituting DependentTy can't fail"); - return TDK_Success; + return TemplateDeductionResult::Success; } return TDK; }; @@ -5037,7 +5076,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, if (AT->isDecltypeAuto()) { if (InitList) { Diag(Init->getBeginLoc(), diag::err_decltype_auto_initializer_list); - return TDK_AlreadyDiagnosed; + return TemplateDeductionResult::AlreadyDiagnosed; } DeducedType = getDecltypeForExpr(Init); @@ -5060,24 +5099,25 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, // deduce against that. Such deduction only succeeds if removing // cv-qualifiers and references results in std::initializer_list. if (!Type.getType().getNonReferenceType()->getAs()) - return TDK_Invalid; + return TemplateDeductionResult::Invalid; SourceRange DeducedFromInitRange; for (Expr *Init : InitList->inits()) { // Resolving a core issue: a braced-init-list containing any designators // is a non-deduced context. if (isa(Init)) - return TDK_Invalid; + return TemplateDeductionResult::Invalid; if (auto TDK = DeduceTemplateArgumentsFromCallArgument( *this, TemplateParamsSt.get(), 0, TemplArg, Init->getType(), Init->Classify(getASTContext()), Init, Info, Deduced, OriginalCallArgs, /*Decomposed=*/true, - /*ArgIdx=*/0, /*TDF=*/0)) { - if (TDK == TDK_Inconsistent) { + /*ArgIdx=*/0, /*TDF=*/0); + TDK != TemplateDeductionResult::Success) { + if (TDK == TemplateDeductionResult::Inconsistent) { Diag(Info.getLocation(), diag::err_auto_inconsistent_deduction) << Info.FirstArg << Info.SecondArg << DeducedFromInitRange << Init->getSourceRange(); - return DeductionFailed(TDK_AlreadyDiagnosed); + return DeductionFailed(TemplateDeductionResult::AlreadyDiagnosed); } return DeductionFailed(TDK); } @@ -5089,7 +5129,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, } else { if (!getLangOpts().CPlusPlus && Init->refersToBitField()) { Diag(Loc, diag::err_auto_bitfield); - return TDK_AlreadyDiagnosed; + return TemplateDeductionResult::AlreadyDiagnosed; } QualType FuncParam = SubstituteDeducedTypeTransform(*this, TemplArg).Apply(Type); @@ -5099,19 +5139,20 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, *this, TemplateParamsSt.get(), 0, FuncParam, Init->getType(), Init->Classify(getASTContext()), Init, Info, Deduced, OriginalCallArgs, /*Decomposed=*/false, /*ArgIdx=*/0, /*TDF=*/0, - FailedTSC)) + FailedTSC); + TDK != TemplateDeductionResult::Success) return DeductionFailed(TDK); } // Could be null if somehow 'auto' appears in a non-deduced context. if (Deduced[0].getKind() != TemplateArgument::Type) - return DeductionFailed(TDK_Incomplete); + return DeductionFailed(TemplateDeductionResult::Incomplete); DeducedType = Deduced[0].getAsType(); if (InitList) { DeducedType = BuildStdInitializerList(DeducedType, Loc); if (DeducedType.isNull()) - return TDK_AlreadyDiagnosed; + return TemplateDeductionResult::AlreadyDiagnosed; } } @@ -5119,7 +5160,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, if (!Context.hasSameType(DeducedType, Result)) { Info.FirstArg = Result; Info.SecondArg = DeducedType; - return DeductionFailed(TDK_Inconsistent); + return DeductionFailed(TemplateDeductionResult::Inconsistent); } DeducedType = Context.getCommonSugaredType(Result, DeducedType); } @@ -5127,11 +5168,11 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, if (AT->isConstrained() && !IgnoreConstraints && CheckDeducedPlaceholderConstraints( *this, *AT, Type.getContainedAutoTypeLoc(), DeducedType)) - return TDK_AlreadyDiagnosed; + return TemplateDeductionResult::AlreadyDiagnosed; Result = SubstituteDeducedTypeTransform(*this, DeducedType).Apply(Type); if (Result.isNull()) - return TDK_AlreadyDiagnosed; + return TemplateDeductionResult::AlreadyDiagnosed; // Check that the deduced argument type is compatible with the original // argument type per C++ [temp.deduct.call]p4. @@ -5140,13 +5181,14 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, assert((bool)InitList == OriginalArg.DecomposedParam && "decomposed non-init-list in auto deduction?"); if (auto TDK = - CheckOriginalCallArgDeduction(*this, Info, OriginalArg, DeducedA)) { + CheckOriginalCallArgDeduction(*this, Info, OriginalArg, DeducedA); + TDK != TemplateDeductionResult::Success) { Result = QualType(); return DeductionFailed(TDK); } } - return TDK_Success; + return TemplateDeductionResult::Success; } QualType Sema::SubstAutoType(QualType TypeWithAuto, @@ -5403,7 +5445,8 @@ static bool isAtLeastAsSpecializedAs(Sema &S, if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(), Args1.data(), Args1.size(), Info, Deduced, - TDF_None, /*PartialOrdering=*/true)) + TDF_None, /*PartialOrdering=*/true) != + TemplateDeductionResult::Success) return false; break; @@ -5415,17 +5458,17 @@ static bool isAtLeastAsSpecializedAs(Sema &S, if (DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, Proto2->getReturnType(), Proto1->getReturnType(), Info, Deduced, TDF_None, - /*PartialOrdering=*/true)) + /*PartialOrdering=*/true) != TemplateDeductionResult::Success) return false; break; case TPOC_Other: // - In other contexts (14.6.6.2) the function template's function type // is used. - if (DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, - FD2->getType(), FD1->getType(), - Info, Deduced, TDF_None, - /*PartialOrdering=*/true)) + if (DeduceTemplateArgumentsByTypeMatch( + S, TemplateParams, FD2->getType(), FD1->getType(), Info, Deduced, + TDF_None, + /*PartialOrdering=*/true) != TemplateDeductionResult::Success) return false; break; } @@ -5599,9 +5642,12 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate( Sema::TPL_TemplateParamsEquivalent)) return nullptr; + // [dcl.fct]p5: + // Any top-level cv-qualifiers modifying a parameter type are deleted when + // forming the function type. for (unsigned i = 0; i < NumParams1; ++i) - if (!Context.hasSameType(FD1->getParamDecl(i)->getType(), - FD2->getParamDecl(i)->getType())) + if (!Context.hasSameUnqualifiedType(FD1->getParamDecl(i)->getType(), + FD2->getParamDecl(i)->getType())) return nullptr; // C++20 [temp.func.order]p6.3: @@ -5776,9 +5822,9 @@ static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2, // Determine whether P1 is at least as specialized as P2. Deduced.resize(P2->getTemplateParameters()->size()); - if (DeduceTemplateArgumentsByTypeMatch(S, P2->getTemplateParameters(), - T2, T1, Info, Deduced, TDF_None, - /*PartialOrdering=*/true)) + if (DeduceTemplateArgumentsByTypeMatch( + S, P2->getTemplateParameters(), T2, T1, Info, Deduced, TDF_None, + /*PartialOrdering=*/true) != TemplateDeductionResult::Success) return false; SmallVector DeducedArgs(Deduced.begin(), @@ -5791,9 +5837,10 @@ static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2, const auto *TST1 = cast(T1); bool AtLeastAsSpecialized; S.runWithSufficientStackSpace(Info.getLocation(), [&] { - AtLeastAsSpecialized = !FinishTemplateArgumentDeduction( - S, P2, /*IsPartialOrdering=*/true, TST1->template_arguments(), Deduced, - Info); + AtLeastAsSpecialized = + FinishTemplateArgumentDeduction( + S, P2, /*IsPartialOrdering=*/true, TST1->template_arguments(), + Deduced, Info) == TemplateDeductionResult::Success; }); return AtLeastAsSpecialized; } diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 6d59180bc446d21e004de01e9a6d0965602e20cf..371378485626c2cfccbe1f0e20e49cd8875b008c 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -3693,9 +3693,9 @@ bool Sema::usesPartialOrExplicitSpecialization( ->getPartialSpecializations(PartialSpecs); for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) { TemplateDeductionInfo Info(Loc); - if (!DeduceTemplateArguments(PartialSpecs[I], - ClassTemplateSpec->getTemplateArgs().asArray(), - Info)) + if (DeduceTemplateArguments(PartialSpecs[I], + ClassTemplateSpec->getTemplateArgs().asArray(), + Info) == TemplateDeductionResult::Success) return true; } @@ -3739,8 +3739,9 @@ getPatternForClassTemplateSpecialization( for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) { ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I]; TemplateDeductionInfo Info(FailedCandidates.getLocation()); - if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments( - Partial, ClassTemplateSpec->getTemplateArgs().asArray(), Info)) { + if (TemplateDeductionResult Result = S.DeduceTemplateArguments( + Partial, ClassTemplateSpec->getTemplateArgs().asArray(), Info); + Result != TemplateDeductionResult::Success) { // Store the failed-deduction information for use in diagnostics, later. // TODO: Actually use the failed-deduction info? FailedCandidates.addCandidate().set( diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 3ed17c3360a83c8f075a116c1d90b66cc1443462..6e5ae123a6ba2cd2dff5df05b2a93665c237d63c 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -27,6 +27,7 @@ #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/OpenMPKinds.h" @@ -3995,6 +3996,13 @@ public: return getSema().CreateRecoveryExpr(BeginLoc, EndLoc, SubExprs, Type); } + StmtResult RebuildOpenACCComputeConstruct(OpenACCDirectiveKind K, + SourceLocation BeginLoc, + SourceLocation EndLoc, + StmtResult StrBlock) { + llvm_unreachable("Not yet implemented!"); + } + private: TypeLoc TransformTypeInObjectScope(TypeLoc TL, QualType ObjectType, @@ -10993,6 +11001,21 @@ OMPClause *TreeTransform::TransformOMPXBareClause(OMPXBareClause *C) { return getDerived().RebuildOMPXBareClause(C->getBeginLoc(), C->getEndLoc()); } +//===----------------------------------------------------------------------===// +// OpenACC transformation +//===----------------------------------------------------------------------===// +template +StmtResult TreeTransform::TransformOpenACCComputeConstruct( + OpenACCComputeConstruct *C) { + // TODO OpenACC: Transform clauses. + + // Transform Structured Block. + StmtResult StrBlock = getDerived().TransformStmt(C->getStructuredBlock()); + + return getDerived().RebuildOpenACCComputeConstruct( + C->getDirectiveKind(), C->getBeginLoc(), C->getEndLoc(), StrBlock); +} + //===----------------------------------------------------------------------===// // Expression transformation //===----------------------------------------------------------------------===// diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index c9217f7aac087e3012a15c267e47295ccc14fbf0..eea14a66fa1818d3d6034626c7d19eb57202b254 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -987,9 +987,13 @@ ASTIdentifierLookupTraitBase::ReadKey(const unsigned char* d, unsigned n) { /// Whether the given identifier is "interesting". static bool isInterestingIdentifier(ASTReader &Reader, IdentifierInfo &II, bool IsModule) { + bool IsInteresting = + II.getInterestingIdentifierID() != + tok::InterestingIdentifierKind::not_interesting || + II.getBuiltinID() != Builtin::ID::NotBuiltin || + II.getObjCKeywordID() != tok::ObjCKeywordKind::objc_not_keyword; return II.hadMacroDefinition() || II.isPoisoned() || - (!IsModule && II.getObjCOrBuiltinID()) || - II.hasRevertedTokenIDToIdentifier() || + (!IsModule && IsInteresting) || II.hasRevertedTokenIDToIdentifier() || (!(IsModule && Reader.getPreprocessor().getLangOpts().CPlusPlus) && II.getFETokenInfo()); } diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index d79f194fd16c60cebca6cd9d5615c78aebb0abf6..3da44ffccc38a280c65d7a7c781703672630416d 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2788,6 +2788,26 @@ void ASTStmtReader::VisitOMPTargetParallelGenericLoopDirective( VisitOMPLoopDirective(D); } +//===----------------------------------------------------------------------===// +// OpenACC Constructs/Directives. +//===----------------------------------------------------------------------===// +void ASTStmtReader::VisitOpenACCConstructStmt(OpenACCConstructStmt *S) { + S->Kind = Record.readEnum(); + S->Range = Record.readSourceRange(); + // TODO OpenACC: Deserialize Clauses. +} + +void ASTStmtReader::VisitOpenACCAssociatedStmtConstruct( + OpenACCAssociatedStmtConstruct *S) { + VisitOpenACCConstructStmt(S); + S->setAssociatedStmt(Record.readSubStmt()); +} + +void ASTStmtReader::VisitOpenACCComputeConstruct(OpenACCComputeConstruct *S) { + VisitStmt(S); + VisitOpenACCConstructStmt(S); +} + //===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// @@ -4206,6 +4226,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) ConceptSpecializationExpr(Empty); break; } + case STMT_OPENACC_COMPUTE_CONSTRUCT: + S = OpenACCComputeConstruct::CreateEmpty(Context, Empty); + break; case EXPR_REQUIRES: unsigned numLocalParameters = Record[ASTStmtReader::NumExprFields]; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 83ad4cb5b5602f55c32af7969ff1ed600ac49cc6..7966b3175ec9f1603eee7756ff873aed27e1698b 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -3597,8 +3597,13 @@ class ASTIdentifierTableTrait { /// doesn't check whether the name has macros defined; use PublicMacroIterator /// to check that. bool isInterestingIdentifier(const IdentifierInfo *II, uint64_t MacroOffset) { - if (MacroOffset || II->isPoisoned() || - (!IsModule && II->getObjCOrBuiltinID()) || + II->getObjCOrBuiltinID(); + bool IsInteresting = + II->getInterestingIdentifierID() != + tok::InterestingIdentifierKind::not_interesting || + II->getBuiltinID() != Builtin::ID::NotBuiltin || + II->getObjCKeywordID() != tok::ObjCKeywordKind::objc_not_keyword; + if (MacroOffset || II->isPoisoned() || (!IsModule && IsInteresting) || II->hasRevertedTokenIDToIdentifier() || (NeedDecls && II->getFETokenInfo())) return true; diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 5b0b90234c410b5b446efc20472eb4f95aa86309..484621ae813093ed071517f2cf3a53001c431a38 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2838,6 +2838,27 @@ void ASTStmtWriter::VisitOMPTargetParallelGenericLoopDirective( Code = serialization::STMT_OMP_TARGET_PARALLEL_GENERIC_LOOP_DIRECTIVE; } +//===----------------------------------------------------------------------===// +// OpenACC Constructs/Directives. +//===----------------------------------------------------------------------===// +void ASTStmtWriter::VisitOpenACCConstructStmt(OpenACCConstructStmt *S) { + Record.writeEnum(S->Kind); + Record.AddSourceRange(S->Range); + // TODO OpenACC: Serialize Clauses. +} + +void ASTStmtWriter::VisitOpenACCAssociatedStmtConstruct( + OpenACCAssociatedStmtConstruct *S) { + VisitOpenACCConstructStmt(S); + Record.AddStmt(S->getAssociatedStmt()); +} + +void ASTStmtWriter::VisitOpenACCComputeConstruct(OpenACCComputeConstruct *S) { + VisitStmt(S); + VisitOpenACCConstructStmt(S); + Code = serialization::STMT_OPENACC_COMPUTE_CONSTRUCT; +} + //===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index 0c6293e67a86f29438dbfa20dda91bcc9fe27138..6b8ac2629453d462be72160e7a06d0a62bb505b3 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -2023,13 +2023,6 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( {{EOFv, EOFv}, {0, UCharRangeMax}}, "an unsigned char value or EOF"))); - // The getc() family of functions that returns either a char or an EOF. - addToFunctionSummaryMap( - {"getc", "fgetc"}, Signature(ArgTypes{FilePtrTy}, RetType{IntTy}), - Summary(NoEvalCall) - .Case({ReturnValueCondition(WithinRange, - {{EOFv, EOFv}, {0, UCharRangeMax}})}, - ErrnoIrrelevant)); addToFunctionSummaryMap( "getchar", Signature(ArgTypes{}, RetType{IntTy}), Summary(NoEvalCall) @@ -2139,7 +2132,17 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( std::move(GetenvSummary)); } - if (ModelPOSIX) { + if (!ModelPOSIX) { + // Without POSIX use of 'errno' is not specified (in these cases). + // Add these functions without 'errno' checks. + addToFunctionSummaryMap( + {"getc", "fgetc"}, Signature(ArgTypes{FilePtrTy}, RetType{IntTy}), + Summary(NoEvalCall) + .Case({ReturnValueCondition(WithinRange, + {{EOFv, EOFv}, {0, UCharRangeMax}})}, + ErrnoIrrelevant) + .ArgConstraint(NotNull(ArgNo(0)))); + } else { const auto ReturnsZeroOrMinusOne = ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, 0))}; const auto ReturnsZero = @@ -2231,6 +2234,63 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg) .ArgConstraint(NotNull(ArgNo(0)))); + std::optional Off_tTy = lookupTy("off_t"); + std::optional Off_tMax = getMaxValue(Off_tTy); + + // int fgetc(FILE *stream); + // 'getc' is the same as 'fgetc' but may be a macro + addToFunctionSummaryMap( + {"getc", "fgetc"}, Signature(ArgTypes{FilePtrTy}, RetType{IntTy}), + Summary(NoEvalCall) + .Case({ReturnValueCondition(WithinRange, {{0, UCharRangeMax}})}, + ErrnoMustNotBeChecked, GenericSuccessMsg) + .Case({ReturnValueCondition(WithinRange, SingleValue(EOFv))}, + ErrnoIrrelevant, GenericFailureMsg) + .ArgConstraint(NotNull(ArgNo(0)))); + + // int fputc(int c, FILE *stream); + // 'putc' is the same as 'fputc' but may be a macro + addToFunctionSummaryMap( + {"putc", "fputc"}, + Signature(ArgTypes{IntTy, FilePtrTy}, RetType{IntTy}), + Summary(NoEvalCall) + .Case({ArgumentCondition(0, WithinRange, Range(0, UCharRangeMax)), + ReturnValueCondition(BO_EQ, ArgNo(0))}, + ErrnoMustNotBeChecked, GenericSuccessMsg) + .Case({ArgumentCondition(0, OutOfRange, Range(0, UCharRangeMax)), + ReturnValueCondition(WithinRange, Range(0, UCharRangeMax))}, + ErrnoMustNotBeChecked, GenericSuccessMsg) + .Case({ReturnValueCondition(WithinRange, SingleValue(EOFv))}, + ErrnoNEZeroIrrelevant, GenericFailureMsg) + .ArgConstraint(NotNull(ArgNo(1)))); + + // char *fgets(char *restrict s, int n, FILE *restrict stream); + addToFunctionSummaryMap( + "fgets", + Signature(ArgTypes{CharPtrRestrictTy, IntTy, FilePtrRestrictTy}, + RetType{CharPtrTy}), + Summary(NoEvalCall) + .Case({ReturnValueCondition(BO_EQ, ArgNo(0))}, + ErrnoMustNotBeChecked, GenericSuccessMsg) + .Case({IsNull(Ret)}, ErrnoIrrelevant, GenericFailureMsg) + .ArgConstraint(NotNull(ArgNo(0))) + .ArgConstraint(ArgumentCondition(1, WithinRange, Range(0, IntMax))) + .ArgConstraint( + BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1))) + .ArgConstraint(NotNull(ArgNo(2)))); + + // int fputs(const char *restrict s, FILE *restrict stream); + addToFunctionSummaryMap( + "fputs", + Signature(ArgTypes{ConstCharPtrRestrictTy, FilePtrRestrictTy}, + RetType{IntTy}), + Summary(NoEvalCall) + .Case(ReturnsNonnegative, ErrnoMustNotBeChecked, GenericSuccessMsg) + .Case({ReturnValueCondition(WithinRange, SingleValue(EOFv))}, + ErrnoNEZeroIrrelevant, GenericFailureMsg) + .ArgConstraint(NotNull(ArgNo(0))) + .ArgConstraint(NotNull(ArgNo(1)))); + // int ungetc(int c, FILE *stream); addToFunctionSummaryMap( "ungetc", Signature(ArgTypes{IntTy, FilePtrTy}, RetType{IntTy}), @@ -2250,9 +2310,6 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( 0, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})) .ArgConstraint(NotNull(ArgNo(1)))); - std::optional Off_tTy = lookupTy("off_t"); - std::optional Off_tMax = getMaxValue(Off_tTy); - // int fseek(FILE *stream, long offset, int whence); // FIXME: It can be possible to get the 'SEEK_' values (like EOFv) and use // these for condition of arg 2. diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp index d2b6634105800083381d5e9bcc513ad4b91a5f78..96784d42d09fa46dba3917daf6741d202ab83b3b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp @@ -84,6 +84,7 @@ std::optional isRefCountable(const CXXRecordDecl* R) if (AnyInconclusiveBase) return std::nullopt; + Paths.clear(); const auto hasPublicDerefInBase = [&AnyInconclusiveBase](const CXXBaseSpecifier *Base, CXXBasePath &) { auto hasDerefInBase = clang::hasPublicMethodInBase(Base, "deref"); @@ -154,6 +155,7 @@ std::optional isGetterOfRefCounted(const CXXMethodDecl* M) if (((className == "Ref" || className == "RefPtr") && methodName == "get") || + (className == "Ref" && methodName == "ptr") || ((className == "String" || className == "AtomString" || className == "AtomStringImpl" || className == "UniqueString" || className == "UniqueStringImpl" || className == "Identifier") && diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp index 31ccae8b097b89792004425552fcd24a3a254170..f4e6191cf05a3c4bd02377ece1dd5c8ee8fd14b7 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp @@ -91,6 +91,9 @@ public: const auto *Arg = CE->getArg(ArgIdx); + if (auto *defaultArg = dyn_cast(Arg)) + Arg = defaultArg->getExpr(); + std::pair ArgOrigin = tryToFindPtrOrigin(Arg, true); @@ -125,6 +128,16 @@ public: // of object on LHS. if (auto *MemberOp = dyn_cast(CE)) { // Note: assignemnt to built-in type isn't derived from CallExpr. + if (MemberOp->getOperator() == + OO_Equal) { // Ignore assignment to Ref/RefPtr. + auto *callee = MemberOp->getDirectCallee(); + if (auto *calleeDecl = dyn_cast(callee)) { + if (const CXXRecordDecl *classDecl = calleeDecl->getParent()) { + if (isRefCounted(classDecl)) + return true; + } + } + } if (MemberOp->isAssignmentOp()) return false; } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index ccc3c0f1e0c10023aece2dca36e726aca2355207..09c69f9612d96b8ed81baca77adce23b741e5c79 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1821,6 +1821,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPParallelGenericLoopDirectiveClass: case Stmt::OMPTargetParallelGenericLoopDirectiveClass: case Stmt::CapturedStmtClass: + case Stmt::OpenACCComputeConstructClass: case Stmt::OMPUnrollDirectiveClass: case Stmt::OMPMetaDirectiveClass: { const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState()); diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index 995d8b2899c8d0ebd3e1eab7d9349860c16f4f67..5a9e563c2d5b264b8086a3c8e19a3eb989532746 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -430,14 +430,14 @@ void ModuleDepCollectorPP::LexedFileChanged(FileID FID, void ModuleDepCollectorPP::InclusionDirective( SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, - StringRef SearchPath, StringRef RelativePath, const Module *Imported, - SrcMgr::CharacteristicKind FileType) { - if (!File && !Imported) { + StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) { + if (!File && !ModuleImported) { // This is a non-modular include that HeaderSearch failed to find. Add it // here as `FileChanged` will never see it. MDC.addFileDep(FileName); } - handleImport(Imported); + handleImport(SuggestedModule); } void ModuleDepCollectorPP::moduleImport(SourceLocation ImportLoc, diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp index e14ff34dd7371697e51beb7f2551b4c3493963b5..3c06ab5fbe3657ec475af8028cb27d925e0e1e8b 100644 --- a/clang/test/AST/Interp/arrays.cpp +++ b/clang/test/AST/Interp/arrays.cpp @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++20 -verify %s -// RUN: %clang_cc1 -verify=ref %s -// RUN: %clang_cc1 -verify=ref -std=c++20 %s +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++20 -verify=expected,both %s +// RUN: %clang_cc1 -verify=ref,both %s +// RUN: %clang_cc1 -verify=ref,both -std=c++20 %s constexpr int m = 3; constexpr const int *foo[][5] = { @@ -73,53 +73,40 @@ static_assert(getElementFromEnd(data, 5, 0) == 1, ""); static_assert(getElementFromEnd(data, 5, 4) == 5, ""); constexpr int getFirstElem(const int *a) { - return a[0]; // expected-note {{read of dereferenced null pointer}} \ - // ref-note {{read of dereferenced null pointer}} + return a[0]; // both-note {{read of dereferenced null pointer}} } -static_assert(getFirstElem(nullptr) == 1, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to}} +static_assert(getFirstElem(nullptr) == 1, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} constexpr static int arr[2] = {1,2}; constexpr static int arr2[2] = {3,4}; constexpr int *p1 = nullptr; -constexpr int *p2 = p1 + 1; // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{cannot perform pointer arithmetic on null pointer}} \ - // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{cannot perform pointer arithmetic on null pointer}} +constexpr int *p2 = p1 + 1; // both-error {{must be initialized by a constant expression}} \ + // both-note {{cannot perform pointer arithmetic on null pointer}} constexpr int *p3 = p1 + 0; constexpr int *p4 = p1 - 0; constexpr int *p5 = 0 + p1; -constexpr int *p6 = 0 - p1; // expected-error {{invalid operands to binary expression}} \ - // ref-error {{invalid operands to binary expression}} +constexpr int *p6 = 0 - p1; // both-error {{invalid operands to binary expression}} constexpr int const * ap1 = &arr[0]; -constexpr int const * ap2 = ap1 + 3; // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{cannot refer to element 3 of array of 2}} \ - // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{cannot refer to element 3 of array of 2}} - -constexpr auto ap3 = arr - 1; // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{cannot refer to element -1}} \ - // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{cannot refer to element -1}} +constexpr int const * ap2 = ap1 + 3; // both-error {{must be initialized by a constant expression}} \ + // both-note {{cannot refer to element 3 of array of 2}} + +constexpr auto ap3 = arr - 1; // both-error {{must be initialized by a constant expression}} \ + // both-note {{cannot refer to element -1}} constexpr int k1 = &arr[1] - &arr[0]; static_assert(k1 == 1, ""); static_assert((&arr[0] - &arr[1]) == -1, ""); -constexpr int k2 = &arr2[1] - &arr[0]; // expected-error {{must be initialized by a constant expression}} \ - // ref-error {{must be initialized by a constant expression}} +constexpr int k2 = &arr2[1] - &arr[0]; // both-error {{must be initialized by a constant expression}} static_assert((arr + 0) == arr, ""); static_assert(&arr[0] == arr, ""); static_assert(*(&arr[0]) == 1, ""); static_assert(*(&arr[1]) == 2, ""); -constexpr const int *OOB = (arr + 3) - 3; // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{cannot refer to element 3 of array of 2}} \ - // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{cannot refer to element 3 of array of 2}} +constexpr const int *OOB = (arr + 3) - 3; // both-error {{must be initialized by a constant expression}} \ + // both-note {{cannot refer to element 3 of array of 2}} template constexpr T getElementOf(T* array, int i) { @@ -135,11 +122,8 @@ constexpr T& getElementOfArray(T (&array)[N], int I) { static_assert(getElementOfArray(foo[2], 3) == &m, ""); -static_assert(data[0] == 4, ""); // expected-error{{failed}} \ - // expected-note{{5 == 4}} \ - // ref-error{{failed}} \ - // ref-note{{5 == 4}} - +static_assert(data[0] == 4, ""); // both-error{{failed}} \ + // both-note{{5 == 4}} constexpr int dynamic[] = { f, 3, 2 + 5, data[3], *getElementOf(foo[2], 3) @@ -185,21 +169,15 @@ struct fred y [] = { [0] = { .s[0] = 'q' } }; namespace indices { constexpr int first[] = {1}; - constexpr int firstValue = first[2]; // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{cannot refer to element 2 of array of 1}} \ - // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{cannot refer to element 2 of array of 1}} + constexpr int firstValue = first[2]; // both-error {{must be initialized by a constant expression}} \ + // both-note {{cannot refer to element 2 of array of 1}} constexpr int second[10] = {17}; - constexpr int secondValue = second[10];// ref-error {{must be initialized by a constant expression}} \ - // ref-note {{read of dereferenced one-past-the-end pointer}} \ - // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{read of dereferenced one-past-the-end pointer}} - - constexpr int negative = second[-2]; // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{cannot refer to element -2 of array of 10}} \ - // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{cannot refer to element -2 of array of 10}} + constexpr int secondValue = second[10];// both-error {{must be initialized by a constant expression}} \ + // both-note {{read of dereferenced one-past-the-end pointer}} \ + + constexpr int negative = second[-2]; // both-error {{must be initialized by a constant expression}} \ + // both-note {{cannot refer to element -2 of array of 10}} }; namespace DefaultInit { @@ -222,12 +200,9 @@ public: class AU { public: int a; - constexpr AU() : a(5 / 0) {} // expected-warning {{division by zero is undefined}} \ - // expected-note 2{{division by zero}} \ - // expected-error {{never produces a constant expression}} \ - // ref-error {{never produces a constant expression}} \ - // ref-note 2{{division by zero}} \ - // ref-warning {{division by zero is undefined}} + constexpr AU() : a(5 / 0) {} // both-warning {{division by zero is undefined}} \ + // both-note 2{{division by zero}} \ + // both-error {{never produces a constant expression}} }; class B { public: @@ -241,13 +216,10 @@ static_assert(b.a[1].a == 12, ""); class BU { public: AU a[2]; - constexpr BU() {} // expected-note {{in call to 'AU()'}} \ - // ref-note {{in call to 'AU()'}} + constexpr BU() {} // both-note {{in call to 'AU()'}} }; -constexpr BU bu; // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{in call to 'BU()'}} \ - // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{in call to 'BU()'}} +constexpr BU bu; // both-error {{must be initialized by a constant expression}} \ + // both-note {{in call to 'BU()'}} namespace IncDec { constexpr int getNextElem(const int *A, int I) { @@ -311,62 +283,43 @@ namespace IncDec { } static_assert(getSecondToLast2() == 3, ""); - constexpr int bad1() { // ref-error {{never produces a constant expression}} \ - // expected-error {{never produces a constant expression}} + constexpr int bad1() { // both-error {{never produces a constant expression}} const int *e = E + 3; e++; // This is fine because it's a one-past-the-end pointer - return *e; // expected-note 2{{read of dereferenced one-past-the-end pointer}} \ - // ref-note 2{{read of dereferenced one-past-the-end pointer}} + return *e; // both-note 2{{read of dereferenced one-past-the-end pointer}} } - static_assert(bad1() == 0, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to}} + static_assert(bad1() == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} - constexpr int bad2() { // ref-error {{never produces a constant expression}} \ - // expected-error {{never produces a constant expression}} + constexpr int bad2() { // both-error {{never produces a constant expression}} const int *e = E + 4; - e++; // expected-note 2{{cannot refer to element 5 of array of 4 elements}} \ - // ref-note 2{{cannot refer to element 5 of array of 4 elements}} + e++; // both-note 2{{cannot refer to element 5 of array of 4 elements}} return *e; // This is UB as well } - static_assert(bad2() == 0, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to}} + static_assert(bad2() == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} - - constexpr int bad3() { // ref-error {{never produces a constant expression}} \ - // expected-error {{never produces a constant expression}} + constexpr int bad3() { // both-error {{never produces a constant expression}} const int *e = E; - e--; // expected-note 2{{cannot refer to element -1 of array of 4 elements}} \ - // ref-note 2{{cannot refer to element -1 of array of 4 elements}} + e--; // both-note 2{{cannot refer to element -1 of array of 4 elements}} return *e; // This is UB as well } - static_assert(bad3() == 0, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to}} + static_assert(bad3() == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} constexpr int nullptr1(bool Pre) { int *a = nullptr; if (Pre) - ++a; // ref-note {{arithmetic on null pointer}} \ - // expected-note {{arithmetic on null pointer}} + ++a; // both-note {{arithmetic on null pointer}} else - a++; // ref-note {{arithmetic on null pointer}} \ - // expected-note {{arithmetic on null pointer}} + a++; // both-note {{arithmetic on null pointer}} return 1; } - static_assert(nullptr1(true) == 1, ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to}} - - static_assert(nullptr1(false) == 1, ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to}} + static_assert(nullptr1(true) == 1, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + + static_assert(nullptr1(false) == 1, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} }; namespace ZeroInit { @@ -425,28 +378,20 @@ namespace NoInitMapLeak { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdivision-by-zero" #pragma clang diagnostic ignored "-Wc++20-extensions" - constexpr int testLeak() { // expected-error {{never produces a constant expression}} \ - // ref-error {{never produces a constant expression}} + constexpr int testLeak() { // both-error {{never produces a constant expression}} int a[2]; a[0] = 1; // interrupts interpretation. - (void)(1 / 0); // expected-note 2{{division by zero}} \ - // ref-note 2{{division by zero}} - + (void)(1 / 0); // both-note 2{{division by zero}} return 1; } #pragma clang diagnostic pop - static_assert(testLeak() == 1, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'testLeak()'}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'testLeak()'}} - + static_assert(testLeak() == 1, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to 'testLeak()'}} - constexpr int a[] = {1,2,3,4/0,5}; // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{division by zero}} \ - // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{division by zero}} \ + constexpr int a[] = {1,2,3,4/0,5}; // both-error {{must be initialized by a constant expression}} \ + // both-note {{division by zero}} \ // ref-note {{declared here}} /// FIXME: This should fail in the new interpreter as well. @@ -456,18 +401,13 @@ namespace NoInitMapLeak { static_assert(b == 1, ""); // ref-error {{not an integral constant expression}} \ // ref-note {{not a constant expression}} - constexpr int f() { // expected-error {{never produces a constant expression}} \ - // ref-error {{never produces a constant expression}} - int a[] = {19,2,3/0,4}; // expected-note 2{{division by zero}} \ - // expected-warning {{is undefined}} \ - // ref-note 2{{division by zero}} \ - // ref-warning {{is undefined}} + constexpr int f() { // both-error {{never produces a constant expression}} + int a[] = {19,2,3/0,4}; // both-note 2{{division by zero}} \ + // both-warning {{is undefined}} return 1; } - static_assert(f() == 1, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to}} + static_assert(f() == 1, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} } namespace Incomplete { @@ -477,38 +417,27 @@ namespace Incomplete { }; constexpr Foo F{}; - constexpr const int *A = F.a; // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{array-to-pointer decay of array member without known bound}} \ - // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{array-to-pointer decay of array member without known bound}} - - constexpr const int *B = F.a + 1; // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{array-to-pointer decay of array member without known bound}} \ - // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{array-to-pointer decay of array member without known bound}} - - constexpr int C = *F.a; // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{array-to-pointer decay of array member without known bound}} \ - // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{array-to-pointer decay of array member without known bound}} + constexpr const int *A = F.a; // both-error {{must be initialized by a constant expression}} \ + // both-note {{array-to-pointer decay of array member without known bound}} + constexpr const int *B = F.a + 1; // both-error {{must be initialized by a constant expression}} \ + // both-note {{array-to-pointer decay of array member without known bound}} + constexpr int C = *F.a; // both-error {{must be initialized by a constant expression}} \ + // both-note {{array-to-pointer decay of array member without known bound}} /// These are from test/SemaCXX/constant-expression-cxx11.cpp /// and are the only tests using the 'indexing of array without known bound' diagnostic. /// We currently diagnose them differently. extern int arr[]; // expected-note 3{{declared here}} - constexpr int *c = &arr[1]; // ref-error {{must be initialized by a constant expression}} \ + constexpr int *c = &arr[1]; // both-error {{must be initialized by a constant expression}} \ // ref-note {{indexing of array without known bound}} \ - // expected-error {{must be initialized by a constant expression}} \ // expected-note {{read of non-constexpr variable 'arr'}} - constexpr int *d = &arr[1]; // ref-error {{must be initialized by a constant expression}} \ + constexpr int *d = &arr[1]; // both-error {{must be initialized by a constant expression}} \ // ref-note {{indexing of array without known bound}} \ - // expected-error {{must be initialized by a constant expression}} \ // expected-note {{read of non-constexpr variable 'arr'}} - constexpr int *e = arr + 1; // ref-error {{must be initialized by a constant expression}} \ + constexpr int *e = arr + 1; // both-error {{must be initialized by a constant expression}} \ // ref-note {{indexing of array without known bound}} \ - // expected-error {{must be initialized by a constant expression}} \ // expected-note {{read of non-constexpr variable 'arr'}} } @@ -528,8 +457,7 @@ namespace GH69115 { if (C) return; // Invalid in constexpr. - (void)(1 / 0); // expected-warning {{undefined}} \ - // ref-warning {{undefined}} + (void)(1 / 0); // both-warning {{undefined}} } class F { @@ -569,23 +497,15 @@ namespace GH69115 { namespace NonConstReads { #if __cplusplus >= 202002L - void *p = nullptr; // ref-note {{declared here}} \ - // expected-note {{declared here}} - - int arr[!p]; // ref-error {{not allowed at file scope}} \ - // expected-error {{not allowed at file scope}} \ - // ref-warning {{variable length arrays}} \ - // ref-note {{read of non-constexpr variable 'p'}} \ - // expected-warning {{variable length arrays}} \ - // expected-note {{read of non-constexpr variable 'p'}} - int z; // ref-note {{declared here}} \ - // expected-note {{declared here}} - int a[z]; // ref-error {{not allowed at file scope}} \ - // expected-error {{not allowed at file scope}} \ - // ref-warning {{variable length arrays}} \ - // ref-note {{read of non-const variable 'z'}} \ - // expected-warning {{variable length arrays}} \ - // expected-note {{read of non-const variable 'z'}} + void *p = nullptr; // both-note {{declared here}} + + int arr[!p]; // both-error {{not allowed at file scope}} \ + // both-warning {{variable length arrays}} \ + // both-note {{read of non-constexpr variable 'p'}} + int z; // both-note {{declared here}} + int a[z]; // both-error {{not allowed at file scope}} \ + // both-warning {{variable length arrays}} \ + // both-note {{read of non-const variable 'z'}} #else void *p = nullptr; int arr[!p]; // ref-error {{not allowed at file scope}} \ @@ -598,3 +518,22 @@ namespace NonConstReads { const int y = 0; int yy[y]; } + +namespace SelfComparison { + struct S { + int field; + static int static_field; + int array[4]; + }; + + struct T { + int field; + static int static_field; + int array[4]; + S s; + }; + + int struct_test(S s1, S s2, S *s3, T t) { + return s3->array[t.field] == s3->array[t.field]; // both-warning {{self-comparison always evaluates to true}} + }; +} diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp index d6ed2d862b0949637dbbf99421d2ca943f459353..3aa01d501a3e2ab68becfe91f0aea317fd7d071b 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -1,11 +1,11 @@ -// RUN: %clang_cc1 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify -// RUN: %clang_cc1 -Wno-string-plus-int -fexperimental-new-constant-interpreter -triple i686 %s -verify -// RUN: %clang_cc1 -Wno-string-plus-int -verify=ref %s -Wno-constant-evaluated -// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify -// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter -triple i686 %s -verify -// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -verify=ref %s -Wno-constant-evaluated -// RUN: %clang_cc1 -triple avr -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify -// RUN: %clang_cc1 -triple avr -std=c++20 -Wno-string-plus-int -verify=ref %s -Wno-constant-evaluated +// RUN: %clang_cc1 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify=expected,both +// RUN: %clang_cc1 -Wno-string-plus-int -fexperimental-new-constant-interpreter -triple i686 %s -verify=expected,both +// RUN: %clang_cc1 -Wno-string-plus-int -verify=ref,both %s -Wno-constant-evaluated +// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify=expected,both +// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter -triple i686 %s -verify=expected,both +// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -verify=ref,both %s -Wno-constant-evaluated +// RUN: %clang_cc1 -triple avr -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify=expected,both +// RUN: %clang_cc1 -triple avr -std=c++20 -Wno-string-plus-int -verify=ref,both %s -Wno-constant-evaluated namespace strcmp { @@ -23,23 +23,17 @@ namespace strcmp { static_assert(__builtin_strcmp("abab\0banana", "abab") == 0, ""); static_assert(__builtin_strcmp("abab", "abab\0banana") == 0, ""); static_assert(__builtin_strcmp("abab\0banana", "abab\0canada") == 0, ""); - static_assert(__builtin_strcmp(0, "abab") == 0, ""); // expected-error {{not an integral constant}} \ - // expected-note {{dereferenced null}} \ - // expected-note {{in call to}} \ - // ref-error {{not an integral constant}} \ - // ref-note {{dereferenced null}} - static_assert(__builtin_strcmp("abab", 0) == 0, ""); // expected-error {{not an integral constant}} \ - // expected-note {{dereferenced null}} \ - // expected-note {{in call to}} \ - // ref-error {{not an integral constant}} \ - // ref-note {{dereferenced null}} + static_assert(__builtin_strcmp(0, "abab") == 0, ""); // both-error {{not an integral constant}} \ + // both-note {{dereferenced null}} \ + // expected-note {{in call to}} + static_assert(__builtin_strcmp("abab", 0) == 0, ""); // both-error {{not an integral constant}} \ + // both-note {{dereferenced null}} \ + // expected-note {{in call to}} static_assert(__builtin_strcmp(kFoobar, kFoobazfoobar) == -1, ""); - static_assert(__builtin_strcmp(kFoobar, kFoobazfoobar + 6) == 0, ""); // expected-error {{not an integral constant}} \ - // expected-note {{dereferenced one-past-the-end}} \ - // expected-note {{in call to}} \ - // ref-error {{not an integral constant}} \ - // ref-note {{dereferenced one-past-the-end}} + static_assert(__builtin_strcmp(kFoobar, kFoobazfoobar + 6) == 0, ""); // both-error {{not an integral constant}} \ + // both-note {{dereferenced one-past-the-end}} \ + // expected-note {{in call to}} } /// Copied from constant-expression-cxx11.cpp @@ -69,41 +63,27 @@ constexpr const char *a = "foo\0quux"; static_assert(check(b), ""); static_assert(check(c), ""); - constexpr int over1 = __builtin_strlen(a + 9); // expected-error {{constant expression}} \ - // expected-note {{one-past-the-end}} \ - // expected-note {{in call to}} \ - // ref-error {{constant expression}} \ - // ref-note {{one-past-the-end}} - constexpr int over2 = __builtin_strlen(b + 9); // expected-error {{constant expression}} \ - // expected-note {{one-past-the-end}} \ - // expected-note {{in call to}} \ - // ref-error {{constant expression}} \ - // ref-note {{one-past-the-end}} - constexpr int over3 = __builtin_strlen(c + 9); // expected-error {{constant expression}} \ - // expected-note {{one-past-the-end}} \ - // expected-note {{in call to}} \ - // ref-error {{constant expression}} \ - // ref-note {{one-past-the-end}} - - constexpr int under1 = __builtin_strlen(a - 1); // expected-error {{constant expression}} \ - // expected-note {{cannot refer to element -1}} \ - // ref-error {{constant expression}} \ - // ref-note {{cannot refer to element -1}} - constexpr int under2 = __builtin_strlen(b - 1); // expected-error {{constant expression}} \ - // expected-note {{cannot refer to element -1}} \ - // ref-error {{constant expression}} \ - // ref-note {{cannot refer to element -1}} - constexpr int under3 = __builtin_strlen(c - 1); // expected-error {{constant expression}} \ - // expected-note {{cannot refer to element -1}} \ - // ref-error {{constant expression}} \ - // ref-note {{cannot refer to element -1}} + constexpr int over1 = __builtin_strlen(a + 9); // both-error {{constant expression}} \ + // both-note {{one-past-the-end}} \ + // expected-note {{in call to}} + constexpr int over2 = __builtin_strlen(b + 9); // both-error {{constant expression}} \ + // both-note {{one-past-the-end}} \ + // expected-note {{in call to}} + constexpr int over3 = __builtin_strlen(c + 9); // both-error {{constant expression}} \ + // both-note {{one-past-the-end}} \ + // expected-note {{in call to}} + + constexpr int under1 = __builtin_strlen(a - 1); // both-error {{constant expression}} \ + // both-note {{cannot refer to element -1}} + constexpr int under2 = __builtin_strlen(b - 1); // both-error {{constant expression}} \ + // both-note {{cannot refer to element -1}} + constexpr int under3 = __builtin_strlen(c - 1); // both-error {{constant expression}} \ + // both-note {{cannot refer to element -1}} constexpr char d[] = { 'f', 'o', 'o' }; // no nul terminator. - constexpr int bad = __builtin_strlen(d); // expected-error {{constant expression}} \ - // expected-note {{one-past-the-end}} \ - // expected-note {{in call to}} \ - // ref-error {{constant expression}} \ - // ref-note {{one-past-the-end}} + constexpr int bad = __builtin_strlen(d); // both-error {{constant expression}} \ + // both-note {{one-past-the-end}} \ + // expected-note {{in call to}} } namespace nan { @@ -115,8 +95,7 @@ namespace nan { // expected-error@-2 {{must be initialized by a constant expression}} #endif - constexpr double NaN3 = __builtin_nan("foo"); // expected-error {{must be initialized by a constant expression}} \ - // ref-error {{must be initialized by a constant expression}} + constexpr double NaN3 = __builtin_nan("foo"); // both-error {{must be initialized by a constant expression}} constexpr float NaN4 = __builtin_nanf(""); //constexpr long double NaN5 = __builtin_nanf128(""); @@ -126,8 +105,7 @@ namespace nan { /// FIXME: Current interpreter misses diagnostics. constexpr char f2[] = {'0', 'x', 'A', 'E'}; /// No trailing 0 byte. - constexpr double NaN7 = __builtin_nan(f2); // ref-error {{must be initialized by a constant expression}} \ - // expected-error {{must be initialized by a constant expression}} \ + constexpr double NaN7 = __builtin_nan(f2); // both-error {{must be initialized by a constant expression}} \ // expected-note {{read of dereferenced one-past-the-end pointer}} \ // expected-note {{in call to}} static_assert(!__builtin_issignaling(__builtin_nan("")), ""); @@ -370,9 +348,6 @@ namespace EhReturnDataRegno { case __builtin_eh_return_data_regno(0): // constant foldable. break; } - - __builtin_eh_return_data_regno(X); // expected-error {{argument to '__builtin_eh_return_data_regno' must be a constant integer}} \ - // ref-error {{argument to '__builtin_eh_return_data_regno' must be a constant integer}} - + __builtin_eh_return_data_regno(X); // both-error {{argument to '__builtin_eh_return_data_regno' must be a constant integer}} } } diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index 9ab271a82aeef93b75e32f2bc24d93eb7a1aa91d..85c195d33a96d768832b99d5530d478d0a116ceb 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify -std=c11 %s -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -pedantic -verify=pedantic-expected -std=c11 %s -// RUN: %clang_cc1 -verify=ref -std=c11 %s -// RUN: %clang_cc1 -pedantic -verify=pedantic-ref -std=c11 %s +// RUN: %clang_cc1 -triple x86_64-linux -fexperimental-new-constant-interpreter -verify=expected,all -std=c11 %s +// RUN: %clang_cc1 -triple x86_64-linux -fexperimental-new-constant-interpreter -pedantic -verify=pedantic-expected,all -std=c11 %s +// RUN: %clang_cc1 -triple x86_64-linux -verify=ref,all -std=c11 %s +// RUN: %clang_cc1 -triple x86_64-linux -pedantic -verify=pedantic-ref,all -std=c11 %s typedef __INTPTR_TYPE__ intptr_t; typedef __PTRDIFF_TYPE__ ptrdiff_t; @@ -22,11 +22,9 @@ _Static_assert(!!1.0, ""); // pedantic-ref-warning {{not an integer constant exp _Static_assert(!!1, ""); int a = (1 == 1 ? 5 : 3); -_Static_assert(a == 5, ""); // ref-error {{not an integral constant expression}} \ - // pedantic-ref-error {{not an integral constant expression}} \ - // expected-error {{not an integral constant expression}} \ - // pedantic-expected-error {{not an integral constant expression}} +_Static_assert(a == 5, ""); // all-error {{not an integral constant expression}} +const int DiscardedPtrToIntCast = ((intptr_t)((void*)0), 0); // all-warning {{left operand of comma operator has no effect}} const int b = 3; _Static_assert(b == 3, ""); // pedantic-ref-warning {{not an integer constant expression}} \ @@ -67,25 +65,17 @@ _Static_assert((&a - 100) != 0, ""); // pedantic-ref-warning {{is a GNU extensio /// extern variable of a composite type. /// FIXME: The 'cast from void*' note is missing in the new interpreter. extern struct Test50S Test50; -_Static_assert(&Test50 != (void*)0, ""); // ref-warning {{always true}} \ - // pedantic-ref-warning {{always true}} \ +_Static_assert(&Test50 != (void*)0, ""); // all-warning {{always true}} \ // pedantic-ref-warning {{is a GNU extension}} \ // pedantic-ref-note {{cast from 'void *' is not allowed}} \ - // expected-warning {{always true}} \ - // pedantic-expected-warning {{always true}} \ // pedantic-expected-warning {{is a GNU extension}} struct y {int x,y;}; -int a2[(intptr_t)&((struct y*)0)->y]; // expected-warning {{folded to constant array}} \ - // pedantic-expected-warning {{folded to constant array}} \ - // ref-warning {{folded to constant array}} \ - // pedantic-ref-warning {{folded to constant array}} +int a2[(intptr_t)&((struct y*)0)->y]; // all-warning {{folded to constant array}} const struct y *yy = (struct y*)0; -const intptr_t L = (intptr_t)(&(yy->y)); // expected-error {{not a compile-time constant}} \ - // pedantic-expected-error {{not a compile-time constant}} \ - // ref-error {{not a compile-time constant}} \ - // pedantic-ref-error {{not a compile-time constant}} +const intptr_t L = (intptr_t)(&(yy->y)); // all-error {{not a compile-time constant}} + const ptrdiff_t m = &m + 137 - &m; _Static_assert(m == 137, ""); // pedantic-ref-warning {{GNU extension}} \ // pedantic-expected-warning {{GNU extension}} @@ -93,10 +83,7 @@ _Static_assert(m == 137, ""); // pedantic-ref-warning {{GNU extension}} \ /// from test/Sema/switch.c, used to cause an assertion failure. void f (int z) { while (z) { - default: z--; // expected-error {{'default' statement not in switch}} \ - // pedantic-expected-error {{'default' statement not in switch}} \ - // ref-error {{'default' statement not in switch}} \ - // pedantic-ref-error {{'default' statement not in switch}} + default: z--; // all-error {{'default' statement not in switch}} } } @@ -104,15 +91,8 @@ int expr; int chooseexpr[__builtin_choose_expr(1, 1, expr)]; int somefunc(int i) { - return (i, 65537) * 65537; // expected-warning {{left operand of comma operator has no effect}} \ - // expected-warning {{overflow in expression; result is 131073}} \ - // pedantic-expected-warning {{left operand of comma operator has no effect}} \ - // pedantic-expected-warning {{overflow in expression; result is 131073}} \ - // ref-warning {{left operand of comma operator has no effect}} \ - // ref-warning {{overflow in expression; result is 131073}} \ - // pedantic-ref-warning {{left operand of comma operator has no effect}} \ - // pedantic-ref-warning {{overflow in expression; result is 131073}} - + return (i, 65537) * 65537; // all-warning {{left operand of comma operator has no effect}} \ + // all-warning {{overflow in expression; result is 131073}} } /// FIXME: The following test is incorrect in the new interpreter. @@ -129,3 +109,19 @@ _Static_assert(sizeof(name2) == 0, ""); // expected-error {{failed}} \ // expected-note {{evaluates to}} \ // pedantic-expected-error {{failed}} \ // pedantic-expected-note {{evaluates to}} + +#ifdef __SIZEOF_INT128__ +void *PR28739d = &(&PR28739d)[(__int128)(unsigned long)-1]; // all-warning {{refers past the last possible element}} +#endif + +extern float global_float; +struct XX { int a, *b; }; +struct XY { int before; struct XX xx, *xp; float* after; } xy[] = { + 0, 0, &xy[0].xx.a, &xy[0].xx, &global_float, + [1].xx = 0, &xy[1].xx.a, &xy[1].xx, &global_float, + 0, // all-note {{previous initialization is here}} + 0, // all-note {{previous initialization is here}} + [2].before = 0, // all-warning {{initializer overrides prior initialization of this subobject}} + 0, // all-warning {{initializer overrides prior initialization of this subobject}} + &xy[2].xx.a, &xy[2].xx, &global_float +}; diff --git a/clang/test/AST/Interp/complex.c b/clang/test/AST/Interp/complex.c new file mode 100644 index 0000000000000000000000000000000000000000..b07d0241da12d60c62172ae984b32b2dc730bf99 --- /dev/null +++ b/clang/test/AST/Interp/complex.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both -Wno-unused-value %s +// RUN: %clang_cc1 -verify=ref,both -Wno-unused-value %s + +// expected-no-diagnostics +// ref-no-diagnostics + +void blah() { + __complex__ unsigned xx; + __complex__ signed yy; + __complex__ int result; + + /// The following line calls into the constant interpreter. + result = xx * yy; +} diff --git a/clang/test/AST/Interp/complex.cpp b/clang/test/AST/Interp/complex.cpp index 7d625ab1f378ecfc9100f6ff261d4c6689260b83..9fdaabd9081d56f54a0fffc4bb403931db7e785f 100644 --- a/clang/test/AST/Interp/complex.cpp +++ b/clang/test/AST/Interp/complex.cpp @@ -98,8 +98,9 @@ constexpr _Complex int I3 = {15}; static_assert(__real(I3) == 15, ""); static_assert(__imag(I3) == 0, ""); -/// FIXME: This should work in the new interpreter as well. -// constexpr _Complex _BitInt(8) A = 0;// = {4}; +constexpr _Complex _BitInt(8) A = {4}; +static_assert(__real(A) == 4, ""); +static_assert(__imag(A) == 0, ""); constexpr _Complex double Doubles[4] = {{1.0, 2.0}}; diff --git a/clang/test/AST/Interp/lambda.cpp b/clang/test/AST/Interp/lambda.cpp index f8400898acc0c05f07a174ee325e0e04adc71ce8..a433e5666e4f4c8a747a2f3d9f09e8cc0069b894 100644 --- a/clang/test/AST/Interp/lambda.cpp +++ b/clang/test/AST/Interp/lambda.cpp @@ -155,6 +155,19 @@ namespace StaticInvoker { return fp(i).a; } static_assert(sv6(12) == 12); + + + /// A generic lambda. + auto GL = [](auto a) { return a; }; + constexpr char (*fp2)(char) = GL; + static_assert(fp2('3') == '3', ""); + + struct GLS { + int a; + }; + auto GL2 = [](auto a) { return GLS{a}; }; + constexpr GLS (*fp3)(char) = GL2; + static_assert(fp3('3').a == '3', ""); } namespace LambdasAsParams { diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index f5b5f77ffc624bb259e13ae0e6ae1a8320be5757..bc994c3191ce8ea7e8a1daf6d41258aedb161438 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -915,6 +915,13 @@ static_assert(ignoredDecls() == 12, ""); namespace DiscardExprs { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-value" + typedef struct _GUID { + __UINT32_TYPE__ Data1; + __UINT16_TYPE__ Data2; + __UINT16_TYPE__ Data3; + __UINT8_TYPE__ Data4[8]; + } GUID; + class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) GuidType; struct A{ int a; }; constexpr int ignoredExprs() { @@ -951,6 +958,8 @@ namespace DiscardExprs { (float)1; (double)1.0f; (signed)4u; + __uuidof(GuidType); + __uuidof(number); // both-error {{cannot call operator __uuidof on a type with no GUID}} return 0; } @@ -1105,3 +1114,13 @@ namespace NonConstReads { static_assert(z == 0, ""); // both-error {{not an integral constant expression}} \ // both-note {{read of non-const variable 'z'}} } + +/// This test passes a MaterializedTemporaryExpr to evaluateAsRValue. +/// That needs to return a null pointer after the lvalue-to-rvalue conversion. +/// We used to fail to do that. +namespace rdar8769025 { + __attribute__((nonnull)) void f1(int * const &p); + void test_f1() { + f1(0); // both-warning{{null passed to a callee that requires a non-null argument}} + } +} diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp index 5ce1e6e09a0b74d82043f17877f91e1290837c33..93da831f3bda0a0d48b8869d57024070a78b8842 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -1,11 +1,11 @@ -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++14 -verify %s -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++20 -verify %s -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple i686 -verify %s -// RUN: %clang_cc1 -verify=ref %s -// RUN: %clang_cc1 -verify=ref -std=c++14 %s -// RUN: %clang_cc1 -verify=ref -std=c++20 %s -// RUN: %clang_cc1 -verify=ref -triple i686 %s +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++14 -verify=expected,both %s +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++20 -verify=expected,both %s +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple i686 -verify=expected,both %s +// RUN: %clang_cc1 -verify=ref,both %s +// RUN: %clang_cc1 -verify=ref,both -std=c++14 %s +// RUN: %clang_cc1 -verify=ref,both -std=c++20 %s +// RUN: %clang_cc1 -verify=ref,both -triple i686 %s /// Used to crash. struct Empty {}; @@ -90,9 +90,8 @@ struct Ints2 { int a = 10; int b; }; -constexpr Ints2 ints22; // expected-error {{without a user-provided default constructor}} \ - // expected-error {{must be initialized by a constant expression}} \ - // ref-error {{without a user-provided default constructor}} +constexpr Ints2 ints22; // both-error {{without a user-provided default constructor}} \ + // expected-error {{must be initialized by a constant expression}} constexpr Ints2 I2 = Ints2{12, 25}; static_assert(I2.a == 12, ""); @@ -164,17 +163,13 @@ constexpr C RVOAndParams(int a) { } constexpr C RVOAndParamsResult2 = RVOAndParams(12); -class Bar { // expected-note {{definition of 'Bar' is not complete}} \ - // ref-note {{definition of 'Bar' is not complete}} +class Bar { // both-note {{definition of 'Bar' is not complete}} public: constexpr Bar(){} - constexpr Bar b; // expected-error {{cannot be constexpr}} \ - // expected-error {{has incomplete type 'const Bar'}} \ - // ref-error {{cannot be constexpr}} \ - // ref-error {{has incomplete type 'const Bar'}} + constexpr Bar b; // both-error {{cannot be constexpr}} \ + // both-error {{has incomplete type 'const Bar'}} }; -constexpr Bar B; // expected-error {{must be initialized by a constant expression}} \ - // ref-error {{must be initialized by a constant expression}} +constexpr Bar B; // both-error {{must be initialized by a constant expression}} constexpr Bar *pb = nullptr; constexpr int locals() { @@ -198,17 +193,13 @@ namespace thisPointer { constexpr int get12() { return 12; } }; - constexpr int foo() { // ref-error {{never produces a constant expression}} \ - // expected-error {{never produces a constant expression}} + constexpr int foo() { // both-error {{never produces a constant expression}} S *s = nullptr; - return s->get12(); // ref-note 2{{member call on dereferenced null pointer}} \ - // expected-note 2{{member call on dereferenced null pointer}} + return s->get12(); // both-note 2{{member call on dereferenced null pointer}} } - static_assert(foo() == 12, ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'foo()'}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'foo()'}} + static_assert(foo() == 12, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to 'foo()'}} }; struct FourBoolPairs { @@ -244,20 +235,16 @@ constexpr A a{}; static_assert(a.i == 100, ""); constexpr A a2{12}; static_assert(a2.i == 12, ""); -static_assert(a2.i == 200, ""); // ref-error {{static assertion failed}} \ - // ref-note {{evaluates to '12 == 200'}} \ - // expected-error {{static assertion failed}} \ - // expected-note {{evaluates to '12 == 200'}} +static_assert(a2.i == 200, ""); // both-error {{static assertion failed}} \ + // both-note {{evaluates to '12 == 200'}} struct S { int a = 0; constexpr int get5() const { return 5; } constexpr void fo() const { - this; // expected-warning {{expression result unused}} \ - // ref-warning {{expression result unused}} - this->a; // expected-warning {{expression result unused}} \ - // ref-warning {{expression result unused}} + this; // both-warning {{expression result unused}} + this->a; // both-warning {{expression result unused}} get5(); getInts(); } @@ -342,12 +329,9 @@ namespace InitializerTemporaries { // Invalid destructor. struct S { constexpr S() {} - constexpr ~S() noexcept(false) { throw 12; } // expected-error {{cannot use 'throw'}} \ - // expected-error {{never produces a constant expression}} \ - // expected-note 2{{subexpression not valid}} \ - // ref-error {{cannot use 'throw'}} \ - // ref-error {{never produces a constant expression}} \ - // ref-note 2{{subexpression not valid}} + constexpr ~S() noexcept(false) { throw 12; } // both-error {{cannot use 'throw'}} \ + // both-error {{never produces a constant expression}} \ + // both-note 2{{subexpression not valid}} }; constexpr int f() { @@ -355,10 +339,8 @@ namespace InitializerTemporaries { /// FIXME: Wrong source location below. return 12; // expected-note {{in call to '&S{}->~S()'}} } - static_assert(f() == 12); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'f()'}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'f()'}} + static_assert(f() == 12); // both-error {{not an integral constant expression}} \ + // both-note {{in call to 'f()'}} #endif @@ -423,7 +405,8 @@ namespace MI { namespace DeriveFailures { #if __cplusplus < 202002L - struct Base { // ref-note 2{{declared here}} expected-note {{declared here}} + struct Base { // both-note {{declared here}} \ + // ref-note {{declared here}} int Val; }; @@ -431,35 +414,29 @@ namespace DeriveFailures { int OtherVal; constexpr Derived(int i) : OtherVal(i) {} // ref-error {{never produces a constant expression}} \ - // ref-note 2{{non-constexpr constructor 'Base' cannot be used in a constant expression}} \ - // expected-note {{non-constexpr constructor 'Base' cannot be used in a constant expression}} + // both-note {{non-constexpr constructor 'Base' cannot be used in a constant expression}} \ + // ref-note {{non-constexpr constructor 'Base' cannot be used in a constant expression}} }; - constexpr Derived D(12); // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{in call to 'Derived(12)'}} \ - // ref-note {{declared here}} \ - // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{in call to 'Derived(12)'}} + constexpr Derived D(12); // both-error {{must be initialized by a constant expression}} \ + // both-note {{in call to 'Derived(12)'}} \ + // ref-note {{declared here}} - static_assert(D.Val == 0, ""); // ref-error {{not an integral constant expression}} \ + static_assert(D.Val == 0, ""); // both-error {{not an integral constant expression}} \ // ref-note {{initializer of 'D' is not a constant expression}} \ - // expected-error {{not an integral constant expression}} \ // expected-note {{read of uninitialized object}} #endif struct AnotherBase { int Val; - constexpr AnotherBase(int i) : Val(12 / i) {} //ref-note {{division by zero}} \ - //expected-note {{division by zero}} + constexpr AnotherBase(int i) : Val(12 / i) {} // both-note {{division by zero}} }; struct AnotherDerived : AnotherBase { constexpr AnotherDerived(int i) : AnotherBase(i) {} }; - constexpr AnotherBase Derp(0); // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{in call to 'AnotherBase(0)'}} \ - // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{in call to 'AnotherBase(0)'}} + constexpr AnotherBase Derp(0); // both-error {{must be initialized by a constant expression}} \ + // both-note {{in call to 'AnotherBase(0)'}} struct YetAnotherBase { int Val; @@ -467,17 +444,14 @@ namespace DeriveFailures { }; struct YetAnotherDerived : YetAnotherBase { - using YetAnotherBase::YetAnotherBase; // ref-note {{declared here}} \ - // expected-note {{declared here}} + using YetAnotherBase::YetAnotherBase; // both-note {{declared here}} int OtherVal; constexpr bool doit() const { return Val == OtherVal; } }; - constexpr YetAnotherDerived Oops(0); // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{constructor inherited from base class 'YetAnotherBase' cannot be used in a constant expression}} \ - // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{constructor inherited from base class 'YetAnotherBase' cannot be used in a constant expression}} + constexpr YetAnotherDerived Oops(0); // both-error {{must be initialized by a constant expression}} \ + // both-note {{constructor inherited from base class 'YetAnotherBase' cannot be used in a constant expression}} }; namespace EmptyCtor { @@ -543,18 +517,10 @@ namespace PointerArith { constexpr B *b1 = &b + 1; constexpr B *b2 = &b + 0; -#if 0 - constexpr A *a2 = &b + 1; // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{cannot access base class of pointer past the end of object}} \ - // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{cannot access base class of pointer past the end of object}} - -#endif - constexpr const int *pn = &(&b + 1)->n; // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{cannot access field of pointer past the end of object}} \ - // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{cannot access field of pointer past the end of object}} - + constexpr A *a2 = &b + 1; // both-error {{must be initialized by a constant expression}} \ + // both-note {{cannot access base class of pointer past the end of object}} + constexpr const int *pn = &(&b + 1)->n; // both-error {{must be initialized by a constant expression}} \ + // both-note {{cannot access field of pointer past the end of object}} } #if __cplusplus >= 202002L @@ -632,12 +598,9 @@ namespace Destructors { struct S { constexpr S() {} - constexpr ~S() { // expected-error {{never produces a constant expression}} \ - // ref-error {{never produces a constant expression}} - int i = 1 / 0; // expected-warning {{division by zero}} \ - // expected-note 2{{division by zero}} \ - // ref-warning {{division by zero}} \ - // ref-note 2{{division by zero}} + constexpr ~S() { // both-error {{never produces a constant expression}} + int i = 1 / 0; // both-warning {{division by zero}} \ + // both-note 2{{division by zero}} } }; constexpr int testS() { @@ -645,10 +608,8 @@ namespace Destructors { return 1; // expected-note {{in call to '&S{}->~S()'}} // FIXME: ^ Wrong line } - static_assert(testS() == 1); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'testS()'}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'testS()'}} + static_assert(testS() == 1); // both-error {{not an integral constant expression}} \ + // both-note {{in call to 'testS()'}} } namespace BaseToDerived { @@ -657,10 +618,8 @@ namespace A { struct B : A { int n; }; struct C : B {}; C c = {}; - constexpr C *pb = (C*)((A*)&c + 1); // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{cannot access derived class of pointer past the end of object}} \ - // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{cannot access derived class of pointer past the end of object}} + constexpr C *pb = (C*)((A*)&c + 1); // both-error {{must be initialized by a constant expression}} \ + // both-note {{cannot access derived class of pointer past the end of object}} } namespace B { struct A {}; @@ -894,10 +853,8 @@ namespace VirtualFromBase { // Virtual f(), not OK. constexpr X> xxs2; constexpr X *q = const_cast>*>(&xxs2); - static_assert(q->f() == sizeof(X), ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{cannot evaluate call to virtual function}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{cannot evaluate call to virtual function}} + static_assert(q->f() == sizeof(X), ""); // both-error {{not an integral constant expression}} \ + // both-note {{cannot evaluate call to virtual function}} } #endif @@ -1070,14 +1027,10 @@ namespace ParenInit { /// Not constexpr! O o1(0); - constinit O o2(0); // ref-error {{variable does not have a constant initializer}} \ - // ref-note {{required by 'constinit' specifier}} \ - // ref-note {{reference to temporary is not a constant expression}} \ - // ref-note {{temporary created here}} \ - // expected-error {{variable does not have a constant initializer}} \ - // expected-note {{required by 'constinit' specifier}} \ - // expected-note {{reference to temporary is not a constant expression}} \ - // expected-note {{temporary created here}} + constinit O o2(0); // both-error {{variable does not have a constant initializer}} \ + // both-note {{required by 'constinit' specifier}} \ + // both-note {{reference to temporary is not a constant expression}} \ + // both-note {{temporary created here}} } #endif @@ -1109,32 +1062,24 @@ namespace AccessOnNullptr { int a; }; - constexpr int a() { // expected-error {{never produces a constant expression}} \ - // ref-error {{never produces a constant expression}} + constexpr int a() { // both-error {{never produces a constant expression}} F *f = nullptr; - f->a = 0; // expected-note 2{{cannot access field of null pointer}} \ - // ref-note 2{{cannot access field of null pointer}} + f->a = 0; // both-note 2{{cannot access field of null pointer}} return f->a; } - static_assert(a() == 0, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'a()'}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'a()'}} + static_assert(a() == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to 'a()'}} - constexpr int a2() { // expected-error {{never produces a constant expression}} \ - // ref-error {{never produces a constant expression}} + constexpr int a2() { // both-error {{never produces a constant expression}} F *f = nullptr; - const int *a = &(f->a); // expected-note 2{{cannot access field of null pointer}} \ - // ref-note 2{{cannot access field of null pointer}} + const int *a = &(f->a); // both-note 2{{cannot access field of null pointer}} return f->a; } - static_assert(a2() == 0, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'a2()'}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'a2()'}} + static_assert(a2() == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to 'a2()'}} } namespace IndirectFieldInit { @@ -1223,3 +1168,74 @@ namespace IndirectFieldInit { #endif } + +namespace InheritedConstructor { + namespace PR47555 { + struct A { + int c; + int d; + constexpr A(int c, int d) : c(c), d(d){} + }; + struct B : A { using A::A; }; + + constexpr B b = {13, 1}; + static_assert(b.c == 13, ""); + static_assert(b.d == 1, ""); + } + + namespace PR47555_2 { + struct A { + int c; + int d; + double e; + constexpr A(int c, int &d, double e) : c(c), d(++d), e(e){} + }; + struct B : A { using A::A; }; + + constexpr int f() { + int a = 10; + B b = {10, a, 40.0}; + return a; + } + static_assert(f() == 11, ""); + } + + namespace AaronsTest { + struct T { + constexpr T(float) {} + }; + + struct Base { + constexpr Base(T t = 1.0f) {} + constexpr Base(float) {} + }; + + struct FirstMiddle : Base { + using Base::Base; + constexpr FirstMiddle() : Base(2.0f) {} + }; + + struct SecondMiddle : Base { + constexpr SecondMiddle() : Base(3.0f) {} + constexpr SecondMiddle(T t) : Base(t) {} + }; + + struct S : FirstMiddle, SecondMiddle { + using FirstMiddle::FirstMiddle; + constexpr S(int i) : S(4.0f) {} + }; + + constexpr S s(1); + } +} + +namespace InvalidCtorInitializer { + struct X { + int Y; + constexpr X() // expected-note {{declared here}} + : Y(fo_o_()) {} // both-error {{use of undeclared identifier 'fo_o_'}} + }; + // no crash on evaluating the constexpr ctor. + constexpr int Z = X().Y; // both-error {{constexpr variable 'Z' must be initialized by a constant expression}} \ + // expected-note {{undefined constructor 'X'}} +} diff --git a/clang/test/AST/ast-print-method-decl.cpp b/clang/test/AST/ast-print-method-decl.cpp index 9f5d11260994420012bba979698d26741aa7c9e7..75dea0cac16be1cd18a132568d283e770cc5bbde 100644 --- a/clang/test/AST/ast-print-method-decl.cpp +++ b/clang/test/AST/ast-print-method-decl.cpp @@ -32,8 +32,7 @@ struct DelegatingCtor2 { // CHECK: struct DelegatingCtor3 { struct DelegatingCtor3 { - // FIXME: template <> should not be output - // CHECK: template <> DelegatingCtor3(auto); + // CHECK: DelegatingCtor3(auto); DelegatingCtor3(auto); // FIXME: Implicitly specialized method should not be output diff --git a/clang/test/Analysis/Checkers/WebKit/assignment-to-refptr.cpp b/clang/test/Analysis/Checkers/WebKit/assignment-to-refptr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b2b4671ed96b13a6486f5e5ee5f2b3471c6114b --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/assignment-to-refptr.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s +// expected-no-diagnostics + +#include "mock-types.h" + +class Node { +public: + Node* nextSibling() const; + + void ref() const; + void deref() const; +}; + +static void removeDetachedChildren(Node* firstChild) +{ + for (RefPtr child = firstChild; child; child = child->nextSibling()); +} diff --git a/clang/test/Analysis/Checkers/WebKit/implicit-cast-to-base-class-with-deref-in-superclass.cpp b/clang/test/Analysis/Checkers/WebKit/implicit-cast-to-base-class-with-deref-in-superclass.cpp new file mode 100644 index 0000000000000000000000000000000000000000..176238f31bd2e40f8c6f847a376b880e562c5c48 --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/implicit-cast-to-base-class-with-deref-in-superclass.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s +// expected-no-diagnostics + +#include "mock-types.h" + +class Base { +public: + virtual ~Base(); + void ref() const; + void deref() const; +}; + +class Event : public Base { +protected: + explicit Event(); +}; + +class SubEvent : public Event { +public: + static Ref create(); +private: + SubEvent() = default; +}; + +void someFunction(Base&); + +static void test() +{ + someFunction(SubEvent::create()); +} diff --git a/clang/test/Analysis/Checkers/WebKit/mock-types.h b/clang/test/Analysis/Checkers/WebKit/mock-types.h index 5f570b8bee8cb86e75a19c3cf955eca93072fb58..cc40487614a83d4609346591ba87e24cc830eb24 100644 --- a/clang/test/Analysis/Checkers/WebKit/mock-types.h +++ b/clang/test/Analysis/Checkers/WebKit/mock-types.h @@ -2,13 +2,14 @@ #define mock_types_1103988513531 template struct Ref { - T t; + T *t; Ref() : t{} {}; Ref(T *) {} - T *get() { return nullptr; } - operator const T &() const { return t; } - operator T &() { return t; } + T *get() { return t; } + T *ptr() { return t; } + operator const T &() const { return *t; } + operator T &() { return *t; } }; template struct RefPtr { @@ -20,6 +21,7 @@ template struct RefPtr { T *operator->() { return t; } T &operator*() { return *t; } RefPtr &operator=(T *) { return *this; } + operator bool() { return t; } }; template bool operator==(const RefPtr &, const RefPtr &) { @@ -39,6 +41,7 @@ template bool operator!=(const RefPtr &, T *) { return false; } template bool operator!=(const RefPtr &, T &) { return false; } struct RefCountable { + static Ref create(); void ref() {} void deref() {} }; diff --git a/clang/test/Analysis/Checkers/WebKit/ref-countable-default-arg-nullptr.cpp b/clang/test/Analysis/Checkers/WebKit/ref-countable-default-arg-nullptr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a1860a5434c8643a30e5c5590d45a7549ed3aea2 --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/ref-countable-default-arg-nullptr.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s + +#include "mock-types.h" + +class Obj { +public: + static Obj* get(); + static RefPtr create(); + void ref() const; + void deref() const; +}; + +void someFunction(Obj*, Obj* = nullptr); +void otherFunction(Obj*, Obj* = Obj::get()); +// expected-warning@-1{{Call argument is uncounted and unsafe [alpha.webkit.UncountedCallArgsChecker]}} +void anotherFunction(Obj*, Obj* = Obj::create().get()); + +void otherFunction() { + someFunction(nullptr); + someFunction(Obj::get()); + // expected-warning@-1{{Call argument is uncounted and unsafe [alpha.webkit.UncountedCallArgsChecker]}} + someFunction(Obj::create().get()); + otherFunction(nullptr); + anotherFunction(nullptr); +} diff --git a/clang/test/Analysis/Checkers/WebKit/ref-ptr-accessor.cpp b/clang/test/Analysis/Checkers/WebKit/ref-ptr-accessor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..560dcfd4bdb094a8d7db05b79a823f364ca02339 --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/ref-ptr-accessor.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s +// expected-no-diagnostics + +#include "mock-types.h" + +void someFunction(RefCountable*); + +void testFunction() +{ + Ref item = RefCountable::create(); + someFunction(item.ptr()); +} diff --git a/clang/test/Analysis/Inputs/std-c-library-functions-POSIX.h b/clang/test/Analysis/Inputs/std-c-library-functions-POSIX.h index 63e22ebdb306027605f5f7339410de6331c262e6..b146068eedb0808954be57e9080a8e6246d352d5 100644 --- a/clang/test/Analysis/Inputs/std-c-library-functions-POSIX.h +++ b/clang/test/Analysis/Inputs/std-c-library-functions-POSIX.h @@ -11,6 +11,7 @@ typedef unsigned long int pthread_t; typedef unsigned long time_t; typedef unsigned long clockid_t; typedef __INT64_TYPE__ off64_t; +typedef __INT64_TYPE__ fpos_t; typedef struct { int a; @@ -42,9 +43,22 @@ FILE *fopen(const char *restrict pathname, const char *restrict mode); FILE *tmpfile(void); FILE *freopen(const char *restrict pathname, const char *restrict mode, FILE *restrict stream); +FILE *fdopen(int fd, const char *mode); int fclose(FILE *stream); +int putc(int c, FILE *stream); +int fputc(int c, FILE *stream); +char *fgets(char *restrict s, int n, FILE *restrict stream); +int fputs(const char *restrict s, FILE *restrict stream); int fseek(FILE *stream, long offset, int whence); +int fgetpos(FILE *restrict stream, fpos_t *restrict pos); +int fsetpos(FILE *stream, const fpos_t *pos); +int fflush(FILE *stream); +long ftell(FILE *stream); int fileno(FILE *stream); +void rewind(FILE *stream); +void clearerr(FILE *stream); +int feof(FILE *stream); +int ferror(FILE *stream); long a64l(const char *str64); char *l64a(long value); int open(const char *path, int oflag, ...); @@ -100,7 +114,6 @@ int pclose(FILE *stream); int close(int fildes); long fpathconf(int fildes, int name); long pathconf(const char *path, int name); -FILE *fdopen(int fd, const char *mode); void rewinddir(DIR *dir); void seekdir(DIR *dirp, long loc); int rand_r(unsigned int *seedp); diff --git a/clang/test/Analysis/bitwise-shift-common.c b/clang/test/Analysis/bitwise-shift-common.c index 39108bc838bf277d7745348d33fd8b531450644a..5f37d9976263ae501a28dcea706adfb9d571ab01 100644 --- a/clang/test/Analysis/bitwise-shift-common.c +++ b/clang/test/Analysis/bitwise-shift-common.c @@ -154,7 +154,7 @@ int expression_tracked_back(void) { //===----------------------------------------------------------------------===// int allow_overflows_and_negative_operands(void) { - // These are all legal under C++ 20 and many compilers accept them under + // These are all legal under C++20 and many compilers accept them under // earlier standards as well. int int_min = 1 << 31; // no-warning int this_overflows = 1027 << 30; // no-warning diff --git a/clang/test/Analysis/std-c-library-functions-POSIX.c b/clang/test/Analysis/std-c-library-functions-POSIX.c index 03aa8e2e00a75dd1bc00ae9b7979af99fdc2b791..b53f3132b86877c8417fe824d51815bce29eaa73 100644 --- a/clang/test/Analysis/std-c-library-functions-POSIX.c +++ b/clang/test/Analysis/std-c-library-functions-POSIX.c @@ -23,10 +23,22 @@ // CHECK: Loaded summary for: FILE *popen(const char *command, const char *type) // CHECK: Loaded summary for: int fclose(FILE *stream) // CHECK: Loaded summary for: int pclose(FILE *stream) +// CHECK: Loaded summary for: int getc(FILE *) +// CHECK: Loaded summary for: int fgetc(FILE *) +// CHECK: Loaded summary for: int putc(int c, FILE *stream) +// CHECK: Loaded summary for: int fputc(int c, FILE *stream) +// CHECK: Loaded summary for: char *fgets(char *restrict s, int n, FILE *restrict stream) +// CHECK: Loaded summary for: int fputs(const char *restrict s, FILE *restrict stream) // CHECK: Loaded summary for: int fseek(FILE *stream, long offset, int whence) -// CHECK: Loaded summary for: int fseeko(FILE *stream, off_t offset, int whence) -// CHECK: Loaded summary for: off_t ftello(FILE *stream) +// CHECK: Loaded summary for: int fgetpos(FILE *restrict stream, fpos_t *restrict pos) +// CHECK: Loaded summary for: int fsetpos(FILE *stream, const fpos_t *pos) +// CHECK: Loaded summary for: int fflush(FILE *stream) +// CHECK: Loaded summary for: long ftell(FILE *stream) // CHECK: Loaded summary for: int fileno(FILE *stream) +// CHECK: Loaded summary for: void rewind(FILE *stream) +// CHECK: Loaded summary for: void clearerr(FILE *stream) +// CHECK: Loaded summary for: int feof(FILE *stream) +// CHECK: Loaded summary for: int ferror(FILE *stream) // CHECK: Loaded summary for: long a64l(const char *str64) // CHECK: Loaded summary for: char *l64a(long value) // CHECK: Loaded summary for: int open(const char *path, int oflag, ...) diff --git a/clang/test/Analysis/std-c-library-functions.c b/clang/test/Analysis/std-c-library-functions.c index b7eb6b284460e5b913733abe9fafac19f39292bf..e6564e2bae76116379d37e6158d64ae8b5205e57 100644 --- a/clang/test/Analysis/std-c-library-functions.c +++ b/clang/test/Analysis/std-c-library-functions.c @@ -53,8 +53,6 @@ // CHECK-NEXT: Loaded summary for: int toupper(int) // CHECK-NEXT: Loaded summary for: int tolower(int) // CHECK-NEXT: Loaded summary for: int toascii(int) -// CHECK-NEXT: Loaded summary for: int getc(FILE *) -// CHECK-NEXT: Loaded summary for: int fgetc(FILE *) // CHECK-NEXT: Loaded summary for: int getchar(void) // CHECK-NEXT: Loaded summary for: unsigned int fread(void *restrict, size_t, size_t, FILE *restrict) // CHECK-NEXT: Loaded summary for: unsigned int fwrite(const void *restrict, size_t, size_t, FILE *restrict) @@ -63,6 +61,8 @@ // CHECK-NEXT: Loaded summary for: ssize_t getline(char **restrict, size_t *restrict, FILE *restrict) // CHECK-NEXT: Loaded summary for: ssize_t getdelim(char **restrict, size_t *restrict, int, FILE *restrict) // CHECK-NEXT: Loaded summary for: char *getenv(const char *) +// CHECK-NEXT: Loaded summary for: int getc(FILE *) +// CHECK-NEXT: Loaded summary for: int fgetc(FILE *) #include "Inputs/std-c-library-functions.h" diff --git a/clang/test/Analysis/stream-error.c b/clang/test/Analysis/stream-error.c index cd4b0093cfcb236f67fbf822496668c8e7a286be..4bab07577ccd53f6a7e4b67b36952f477e4f97fa 100644 --- a/clang/test/Analysis/stream-error.c +++ b/clang/test/Analysis/stream-error.c @@ -491,32 +491,6 @@ void error_ftello(void) { fclose(F); } -void error_fflush_after_fclose(void) { - FILE *F = tmpfile(); - int Ret; - fflush(NULL); // no-warning - if (!F) - return; - if ((Ret = fflush(F)) != 0) - clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}} - fclose(F); - fflush(F); // expected-warning {{Stream might be already closed}} -} - -void error_fflush_on_open_failed_stream(void) { - FILE *F = tmpfile(); - if (!F) { - fflush(F); // no-warning - return; - } - fclose(F); -} - -void error_fflush_on_unknown_stream(FILE *F) { - fflush(F); // no-warning - fclose(F); // no-warning -} - void error_fflush_on_non_null_stream_clear_error_states(void) { FILE *F0 = tmpfile(), *F1 = tmpfile(); // `fflush` clears a non-EOF stream's error state. diff --git a/clang/test/Analysis/stream-noopen.c b/clang/test/Analysis/stream-noopen.c index 8ad101ee1e8c135002c15796e06941fb32b37384..8bd01a90cf8596fa08af2a5c0b33ff60ea9e366c 100644 --- a/clang/test/Analysis/stream-noopen.c +++ b/clang/test/Analysis/stream-noopen.c @@ -57,6 +57,95 @@ void test_fwrite(FILE *F) { clang_analyzer_eval(ferror(F)); // expected-warning {{UNKNOWN}} } +void test_fgetc(FILE *F) { + int Ret = fgetc(F); + clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}} + if (Ret != EOF) { + if (errno) {} // expected-warning {{undefined}} + } else { + clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}} + // expected-warning@-1 {{FALSE}} + } + clang_analyzer_eval(feof(F)); // expected-warning {{UNKNOWN}} + clang_analyzer_eval(ferror(F)); // expected-warning {{UNKNOWN}} +} + +void test_fputc(FILE *F) { + int Ret = fputc('a', F); + clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}} + if (Ret != EOF) { + clang_analyzer_eval(Ret == 'a'); // expected-warning {{TRUE}} + if (errno) {} // expected-warning {{undefined}} + } else { + clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}} + } + clang_analyzer_eval(feof(F)); // expected-warning {{UNKNOWN}} + clang_analyzer_eval(ferror(F)); // expected-warning {{UNKNOWN}} +} + +void test_fgets(char *Buf, int N, FILE *F) { + char *Ret = fgets(Buf, N, F); + clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}} + clang_analyzer_eval(Buf != NULL); // expected-warning {{TRUE}} + clang_analyzer_eval(N >= 0); // expected-warning {{TRUE}} + if (Ret == Buf) { + if (errno) {} // expected-warning {{undefined}} + } else { + clang_analyzer_eval(Ret == 0); // expected-warning {{TRUE}} + clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}} + // expected-warning@-1 {{FALSE}} + } + clang_analyzer_eval(feof(F)); // expected-warning {{UNKNOWN}} + clang_analyzer_eval(ferror(F)); // expected-warning {{UNKNOWN}} + + char Buf1[10]; + Ret = fgets(Buf1, 11, F); // expected-warning {{The 1st argument to 'fgets' is a buffer with size 10}} +} + +void test_fgets_bufsize(FILE *F) { + char Buf[10]; + fgets(Buf, 11, F); // expected-warning {{The 1st argument to 'fgets' is a buffer with size 10}} +} + +void test_fputs(char *Buf, FILE *F) { + int Ret = fputs(Buf, F); + clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}} + clang_analyzer_eval(Buf != NULL); // expected-warning {{TRUE}} + if (Ret >= 0) { + if (errno) {} // expected-warning {{undefined}} + } else { + clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}} + clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}} + } + clang_analyzer_eval(feof(F)); // expected-warning {{UNKNOWN}} + clang_analyzer_eval(ferror(F)); // expected-warning {{UNKNOWN}} +} + +void test_ungetc(FILE *F) { + int Ret = ungetc('X', F); + clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}} + if (Ret == 'X') { + if (errno) {} // expected-warning {{undefined}} + } else { + clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}} + clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}} + } + clang_analyzer_eval(feof(F)); // expected-warning {{UNKNOWN}} + clang_analyzer_eval(ferror(F)); // expected-warning {{UNKNOWN}} +} + +void test_ungetc_EOF(FILE *F, int C) { + int Ret = ungetc(EOF, F); + clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}} + clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}} + clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}} + Ret = ungetc(C, F); + if (Ret == EOF) { + clang_analyzer_eval(C == EOF); // expected-warning {{TRUE}} + // expected-warning@-1{{FALSE}} + } +} + void test_fclose(FILE *F) { int Ret = fclose(F); clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}} @@ -138,28 +227,17 @@ void test_rewind(FILE *F) { rewind(F); } -void test_ungetc(FILE *F) { - int Ret = ungetc('X', F); - clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}} - if (Ret == 'X') { - if (errno) {} // expected-warning {{undefined}} - } else { - clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}} - clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}} - } - clang_analyzer_eval(feof(F)); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(ferror(F)); // expected-warning {{UNKNOWN}} -} - -void test_ungetc_EOF(FILE *F, int C) { - int Ret = ungetc(EOF, F); - clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}} - clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}} - clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}} - Ret = ungetc(C, F); +void test_fflush(FILE *F) { + errno = 0; + int Ret = fflush(F); + clang_analyzer_eval(F != NULL); // expected-warning{{TRUE}} + // expected-warning@-1{{FALSE}} if (Ret == EOF) { - clang_analyzer_eval(C == EOF); // expected-warning {{TRUE}} - // expected-warning@-1{{FALSE}} + clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} + } else { + clang_analyzer_eval(Ret == 0); // expected-warning{{TRUE}} + clang_analyzer_eval(errno == 0); // expected-warning{{TRUE}} + // expected-warning@-1{{FALSE}} } } diff --git a/clang/test/Analysis/stream.c b/clang/test/Analysis/stream.c index 36a9b4e26b07a28ea2ccda9011d234d274192b51..378c9154f8f6a879e8fa03b02ab60e3583e067ed 100644 --- a/clang/test/Analysis/stream.c +++ b/clang/test/Analysis/stream.c @@ -1,7 +1,9 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.unix.Stream -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.unix.Stream,debug.ExprInspection -verify %s #include "Inputs/system-header-simulator.h" +void clang_analyzer_eval(int); + void check_fread(void) { FILE *fp = tmpfile(); fread(0, 0, 0, fp); // expected-warning {{Stream pointer might be NULL}} @@ -316,3 +318,24 @@ void check_leak_noreturn_2(void) { } // expected-warning {{Opened stream never closed. Potential resource leak}} // FIXME: This warning should be placed at the `return` above. // See https://reviews.llvm.org/D83120 about details. + +void fflush_after_fclose(void) { + FILE *F = tmpfile(); + int Ret; + fflush(NULL); // no-warning + if (!F) + return; + if ((Ret = fflush(F)) != 0) + clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}} + fclose(F); + fflush(F); // expected-warning {{Stream might be already closed}} +} + +void fflush_on_open_failed_stream(void) { + FILE *F = tmpfile(); + if (!F) { + fflush(F); // no-warning + return; + } + fclose(F); +} diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p23.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p23.cpp new file mode 100644 index 0000000000000000000000000000000000000000..469c4e091953c36e14c62d0061ebdab80f44b2fa --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p23.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -std=c++20 -pedantic-errors -verify %s + +// FIXME: This should be an error with -pedantic-errors. +template<> // expected-warning {{extraneous template parameter list in template specialization}} +void f(auto); + +template +void f(auto); + +template +struct A { + void g(auto); +}; + +template +void A::g(auto) { } + +template<> +void A::g(auto) { } + +// FIXME: This should be an error with -pedantic-errors. +template<> +template<> // expected-warning {{extraneous template parameter list in template specialization}} +void A::g(auto) { } diff --git a/clang/test/CXX/drs/dr11xx.cpp b/clang/test/CXX/drs/dr11xx.cpp index 86e726ae8c7419208ab05efe38df163a8571c14e..a71a105c7eb20470200b92b17f685a37b1582bb2 100644 --- a/clang/test/CXX/drs/dr11xx.cpp +++ b/clang/test/CXX/drs/dr11xx.cpp @@ -70,3 +70,5 @@ namespace dr1113 { // dr1113: partial } void g() { f(); } } + +// dr1150: na diff --git a/clang/test/CXX/drs/dr124.cpp b/clang/test/CXX/drs/dr124.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c07beb11709c712c15b2f1951934ddfbf75756e7 --- /dev/null +++ b/clang/test/CXX/drs/dr124.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK + +#if __cplusplus == 199711L +#define NOTHROW throw() +#else +#define NOTHROW noexcept(true) +#endif + +namespace dr124 { // dr124: 2.7 + +extern void full_expr_fence() NOTHROW; + +struct A { + A() NOTHROW {} + ~A() NOTHROW {} +}; + +struct B { + B(A = A()) NOTHROW {} + ~B() NOTHROW {} +}; + +void f() { + full_expr_fence(); + B b[2]; + full_expr_fence(); +} + +// CHECK-LABEL: define {{.*}} void @dr124::f()() +// CHECK: call void @dr124::full_expr_fence() +// CHECK: br label %arrayctor.loop +// CHECK-LABEL: arrayctor.loop: +// CHECK: call void @dr124::A::A() +// CHECK: call void @dr124::B::B(dr124::A) +// CHECK: call void @dr124::A::~A() +// CHECK: br {{.*}}, label %arrayctor.cont, label %arrayctor.loop +// CHECK-LABEL: arrayctor.cont: +// CHECK: call void @dr124::full_expr_fence() +// CHECK: br label %arraydestroy.body +// CHECK-LABEL: arraydestroy.body: +// CHECK: call void @dr124::B::~B() +// CHECK-LABEL: } + + +} // namespace dr124 diff --git a/clang/test/CXX/drs/dr14xx.cpp b/clang/test/CXX/drs/dr14xx.cpp index d262f6f9dcab796f0d7105d08496e677a8a2c5e3..58a2b3a0d0275d911b23a8b80ab393dc6fdeb47f 100644 --- a/clang/test/CXX/drs/dr14xx.cpp +++ b/clang/test/CXX/drs/dr14xx.cpp @@ -614,6 +614,30 @@ enum E2 : S::I { e }; #endif } // namespace dr1482 +namespace dr1487 { // dr1487: 3.3 +#if __cplusplus >= 201103L +struct A { // #dr1482-A + struct B { + using A::A; + // since-cxx11-error@-1 {{using declaration refers into 'A::', which is not a base class of 'B'}} + }; + + struct C : A { + // since-cxx11-error@-1 {{base class has incomplete type}} + // since-cxx11-note@#dr1482-A {{definition of 'dr1487::A' is not complete until the closing '}'}} + using A::A; + // since-cxx11-error@-1 {{using declaration refers into 'A::', which is not a base class of 'C'}} + }; + + struct D; +}; + +struct D : A { + using A::A; +}; +#endif +} // namespace dr1487 + namespace dr1490 { // dr1490: 3.7 c++11 #if __cplusplus >= 201103L // List-initialization from a string literal diff --git a/clang/test/CXX/drs/dr15xx.cpp b/clang/test/CXX/drs/dr15xx.cpp index 3d4050a5713f926fe0879de36c802b79a25f53d8..ac503db625ba0e6af7708283f6b749ab04c3ec2a 100644 --- a/clang/test/CXX/drs/dr15xx.cpp +++ b/clang/test/CXX/drs/dr15xx.cpp @@ -360,6 +360,45 @@ namespace dr1563 { // dr1563: yes #endif } +namespace dr1567 { // dr1567: 3.3 +#if __cplusplus >= 201103L +struct B; +struct A { + A(const A&); + A(const B&) = delete; + A(A&&); + A(B&&) = delete; + A(int); // #dr1567-A-int +}; + +struct B: A { // #dr1567-B + using A::A; // #dr1567-using-A + B(double); // #dr1567-B-double +}; + +A a{0}; +B b{1.0}; +// Good, deleted converting ctors are not inherited as copy/move ctors +B b2{b}; +B b3{B{1.0}}; +// Good, copy/move ctors are not inherited +B b4{a}; +// since-cxx11-error@-1 {{no matching constructor for initialization of 'B'}} +// since-cxx11-note@#dr1567-A-int {{candidate inherited constructor not viable: no known conversion from 'A' to 'int' for 1st argument}} +// since-cxx11-note@#dr1567-using-A {{constructor from base class 'A' inherited here}} +// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'A' to 'const B' for 1st argument}} +// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'A' to 'B' for 1st argument}} +// since-cxx11-note@#dr1567-B-double {{candidate constructor not viable: no known conversion from 'A' to 'double' for 1st argument}} +B b5{A{0}}; +// since-cxx11-error@-1 {{no matching constructor for initialization of 'B'}} +// since-cxx11-note@#dr1567-A-int {{candidate inherited constructor not viable: no known conversion from 'A' to 'int' for 1st argument}} +// since-cxx11-note@#dr1567-using-A {{constructor from base class 'A' inherited here}} +// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'A' to 'const B' for 1st argument}} +// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'A' to 'B' for 1st argument}} +// since-cxx11-note@#dr1567-B-double {{candidate constructor not viable: no known conversion from 'A' to 'double' for 1st argument}} +#endif +} + namespace dr1573 { // dr1573: 3.9 #if __cplusplus >= 201103L // ellipsis is inherited (p0136r1 supersedes this part). diff --git a/clang/test/CXX/drs/dr17xx.cpp b/clang/test/CXX/drs/dr17xx.cpp index 885ed00ace0f57be6ee7cb8c9f1b26a736a4311d..2f7e62da7bb60bae0798f9171c458652bb51ad0d 100644 --- a/clang/test/CXX/drs/dr17xx.cpp +++ b/clang/test/CXX/drs/dr17xx.cpp @@ -89,6 +89,23 @@ S s(q); // #dr1736-s #endif } +namespace dr1738 { // dr1738: sup P0136R1 +#if __cplusplus >= 201103L +struct A { + template + A(int, T) {} +}; + +struct B : A { + using A::A; +}; + +// FIXME: this is well-formed since P0136R1 +template B::B(int, double); +// since-cxx11-error@-1 {{explicit instantiation of 'B' does not refer to a function template, variable template, member function, member class, or static data member}} +#endif +} + // dr1748 is in dr1748.cpp namespace dr1753 { // dr1753: 11 diff --git a/clang/test/CXX/drs/dr185.cpp b/clang/test/CXX/drs/dr185.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aff00f1a8764ab9c2a5393f1b83a5cfa0cfb6cb8 --- /dev/null +++ b/clang/test/CXX/drs/dr185.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK + +namespace dr185 { // dr185: 2.7 +struct A { + mutable int value; + explicit A(int i) : value(i) {} + void mutate(int i) const { value = i; } +}; + +int foo() { + A const& t = A(1); + A n(t); + t.mutate(2); + return n.value; +} + +// CHECK-LABEL: define {{.*}} i32 @dr185::foo() +// CHECK: call void @dr185::A::A(int)(ptr {{[^,]*}} %ref.tmp, {{.*}}) +// CHECK: store ptr %ref.tmp, ptr %t +// CHECK-NOT: %t = +// CHECK: [[DR185_T:%.+]] = load ptr, ptr %t +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr {{[^,]*}} %n, ptr {{[^,]*}} [[DR185_T]], {{.*}}) +// CHECK-LABEL: } +} // namespace dr185 diff --git a/clang/test/CXX/drs/dr193.cpp b/clang/test/CXX/drs/dr193.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c010dad50e403580bd21ec136c0075e51a42adba --- /dev/null +++ b/clang/test/CXX/drs/dr193.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK + +#if __cplusplus == 199711L +#define NOTHROW throw() +#else +#define NOTHROW noexcept(true) +#endif + +namespace dr193 { // dr193: 2.7 +struct A { + ~A() NOTHROW {} +}; + +struct B { + ~B() NOTHROW {} +}; + +struct C { + ~C() NOTHROW {} +}; + +struct D : A { + B b; + ~D() NOTHROW { C c; } +}; + +void foo() { + D d; +} + +// skipping over D1 (complete object destructor) +// CHECK-LABEL: define {{.*}} void @dr193::D::~D(){{.*}} +// CHECK-LABEL: define {{.*}} void @dr193::D::~D(){{.*}} +// CHECK-NOT: call void @dr193::A::~A() +// CHECK-NOT: call void @dr193::B::~B() +// CHECK: call void @dr193::C::~C() +// CHECK: call void @dr193::B::~B() +// CHECK: call void @dr193::A::~A() +// CHECK-LABEL: } +} // namespace dr193 diff --git a/clang/test/CXX/drs/dr199.cpp b/clang/test/CXX/drs/dr199.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7517d79680c6fd89711dbf31622701fa9fbe4046 --- /dev/null +++ b/clang/test/CXX/drs/dr199.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK + +#if __cplusplus == 199711L +#define NOTHROW throw() +#else +#define NOTHROW noexcept(true) +#endif + +namespace dr199 { // dr199: 2.8 +struct A { + ~A() NOTHROW {} +}; + +struct B { + ~B() NOTHROW {} +}; + +void foo() { + A(), B(); +} + +// CHECK-LABEL: define {{.*}} void @dr199::foo() +// CHECK-NOT: call void @dr199::A::~A() +// CHECK: call void @dr199::B::~B() +// CHECK: call void @dr199::A::~A() +// CHECK-LABEL: } +} // namespace dr199 diff --git a/clang/test/CXX/drs/dr1xx.cpp b/clang/test/CXX/drs/dr1xx.cpp index 1930de2f070a7a9bfbf221f6877fecf12a765b19..d55033cef1b6458481084e3a08aee33146e11bf0 100644 --- a/clang/test/CXX/drs/dr1xx.cpp +++ b/clang/test/CXX/drs/dr1xx.cpp @@ -306,7 +306,7 @@ namespace dr122 { // dr122: yes } // dr123: na -// dr124: dup 201 +// dr124 is in dr124.cpp // dr125: yes struct dr125_A { struct dr125_B {}; }; // #dr125_B @@ -1169,7 +1169,7 @@ namespace dr184 { // dr184: yes void h() { A().g(); } } -// dr185 FIXME: add codegen test +// dr185 is in dr185.cpp namespace dr187 { // dr187: sup 481 const int Z = 1; @@ -1184,6 +1184,7 @@ namespace dr188 { // dr188: yes } // dr190 FIXME: add codegen test for tbaa +// or implement C++20 std::is_layout_compatible and test it this way int dr191_j; namespace dr191 { // dr191: yes @@ -1215,7 +1216,7 @@ namespace dr191 { // dr191: yes } } -// dr193 FIXME: add codegen test +// dr193 is in dr193.cpp namespace dr194 { // dr194: yes struct A { @@ -1290,4 +1291,4 @@ namespace dr198 { // dr198: yes }; } -// dr199 FIXME: add codegen test +// dr199 is in dr199.cpp diff --git a/clang/test/CXX/drs/dr201.cpp b/clang/test/CXX/drs/dr201.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e864981e13be70964a50ec165f8fb159b6e7744 --- /dev/null +++ b/clang/test/CXX/drs/dr201.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK + +#if __cplusplus == 199711L +#define NOTHROW throw() +#else +#define NOTHROW noexcept(true) +#endif + +namespace dr201 { // dr201: 2.8 + +extern void full_expr_fence() NOTHROW; + +struct A { + ~A() NOTHROW {} +}; + +struct B { + B(A) NOTHROW {} + ~B() NOTHROW {} +}; + +void foo() { + full_expr_fence(); + B b = A(); + full_expr_fence(); +} + +// CHECK-LABEL: define {{.*}} void @dr201::foo() +// CHECK: call void @dr201::full_expr_fence() +// CHECK: call void @dr201::B::B(dr201::A) +// CHECK: call void @dr201::A::~A() +// CHECK: call void @dr201::full_expr_fence() +// CHECK: call void @dr201::B::~B() +// CHECK-LABEL: } + +} // namespace dr201 diff --git a/clang/test/CXX/drs/dr210.cpp b/clang/test/CXX/drs/dr210.cpp new file mode 100644 index 0000000000000000000000000000000000000000..156ee81093b43cb288999f14a02e234bd034a2a3 --- /dev/null +++ b/clang/test/CXX/drs/dr210.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK + +#if __cplusplus == 199711L +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wvariadic-macros" +#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__) +#pragma clang diagnostic pop +#endif + +namespace dr210 { // dr210: 2.7 +struct B { + long i; + B(); + virtual ~B(); +}; + +static_assert(sizeof(B) == 16, ""); + +struct D : B { + long j; + D(); +}; + +static_assert(sizeof(D) == 24, ""); + +void toss(const B* b) { + throw *b; +} + +// CHECK-LABEL: define {{.*}} void @dr210::toss(dr210::B const*) +// CHECK: %[[EXCEPTION:.*]] = call ptr @__cxa_allocate_exception(i64 16) +// CHECK: call void @__cxa_throw(ptr %[[EXCEPTION]], ptr @typeinfo for dr210::B, ptr @dr210::B::~B()) +// CHECK-LABEL: } + +} // namespace dr210 diff --git a/clang/test/CXX/drs/dr22xx.cpp b/clang/test/CXX/drs/dr22xx.cpp index 19518247b5289c3921a320eab4aa5f5065bd3477..3a13cb0471a75dfa51e7e1b019fdde0dfe8828dd 100644 --- a/clang/test/CXX/drs/dr22xx.cpp +++ b/clang/test/CXX/drs/dr22xx.cpp @@ -154,6 +154,47 @@ const D &d3(c); // FIXME ill-formed #endif } +namespace dr2273 { // dr2273: 3.3 +#if __cplusplus >= 201103L +struct A { + A(int = 0) = delete; // #dr2273-A +}; + +struct B : A { // #dr2273-B + using A::A; +}; + +B b; +// since-cxx11-error@-1 {{call to implicitly-deleted default constructor of 'B'}} +// since-cxx11-note@#dr2273-B {{default constructor of 'B' is implicitly deleted because base class 'A' has a deleted default constructor}} +// since-cxx11-note@#dr2273-A {{'A' has been explicitly marked deleted here}} +#endif +} + +namespace dr2277 { // dr2277: partial +#if __cplusplus >= 201103L +struct A { + A(int, int = 0); + void f(int, int = 0); // #dr2277-A-f +}; +struct B : A { + B(int); + using A::A; + + void f(int); // #dr2277-B-f + using A::f; +}; + +void g() { + B b{0}; + b.f(0); // FIXME: this is well-formed for the same reason as initialization of 'b' above + // since-cxx11-error@-1 {{call to member function 'f' is ambiguous}} + // since-cxx11-note@#dr2277-A-f {{candidate function}} + // since-cxx11-note@#dr2277-B-f {{candidate function}} +} +#endif +} + namespace dr2292 { // dr2292: 9 #if __cplusplus >= 201103L template using id = T; diff --git a/clang/test/CXX/drs/dr23xx.cpp b/clang/test/CXX/drs/dr23xx.cpp index 3f8c476427eba87866cb024b18d54a52c43a9f8d..c0463730b6a23ac5a962c936980cbccc112602ea 100644 --- a/clang/test/CXX/drs/dr23xx.cpp +++ b/clang/test/CXX/drs/dr23xx.cpp @@ -147,6 +147,31 @@ enum struct alignas(64) B {}; #endif } // namespace dr2354 +namespace dr2356 { // dr2356: 4 +#if __cplusplus >= 201103L +struct A { + A(); + A(A &&); // #1 + template A(T &&); // #2 +}; +struct B : A { + using A::A; + B(const B &); // #3 + B(B &&) = default; // #4, implicitly deleted + // since-cxx11-warning@-1 {{explicitly defaulted move constructor is implicitly deleted}} + // since-cxx11-note@#dr2356-X {{move constructor of 'B' is implicitly deleted because field 'x' has a deleted move constructor}} + // since-cxx11-note@#dr2356-X {{'X' has been explicitly marked deleted here}} + // since-cxx11-note@-4 {{replace 'default' with 'delete'}} + + struct X { X(X &&) = delete; } x; // #dr2356-X +}; +extern B b1; +B b2 = static_cast(b1); // calls #3: #1, #2, and #4 are not viable +struct C { operator B&&(); }; +B b3 = C(); // calls #3 +#endif +} + #if __cplusplus >= 201402L namespace dr2358 { // dr2358: 16 void f2() { diff --git a/clang/test/CXX/drs/dr2504.cpp b/clang/test/CXX/drs/dr2504.cpp new file mode 100644 index 0000000000000000000000000000000000000000..686ea73cd6a0ee6cf2b70cada6c755b1efcbd105 --- /dev/null +++ b/clang/test/CXX/drs/dr2504.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11 +// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11 +// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11 +// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11 +// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11 +// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11 + +namespace dr2504 { // dr2504: no +#if __cplusplus >= 201103L +struct V { V() = default; V(int); }; +struct Q { Q(); }; +struct A : virtual V, Q { + using V::V; + A() = delete; +}; +int bar() { return 42; } +struct B : A { + B() : A(bar()) {} // ok +}; +struct C : B {}; +void foo() { C c; } // bar is not invoked, because the V subobject is not initialized as part of B +#endif +} + +// FIXME: As specified in the comment above (which comes from an example in the Standard), +// we are not supposed to unconditionally call `bar()` and call a constructor +// inherited from `V`. + +// SINCE-CXX11-LABEL: define linkonce_odr void @dr2504::B::B() +// SINCE-CXX11-NOT: br +// SINCE-CXX11: call noundef i32 @dr2504::bar() +// SINCE-CXX11-NOT: br +// SINCE-CXX11: call void @dr2504::A::A(int) +// SINCE-CXX11-LABEL: } + +// CHECK: {{.*}} diff --git a/clang/test/CXX/drs/dr25xx.cpp b/clang/test/CXX/drs/dr25xx.cpp index 502f03271d9afe2fd5f42ba371bf8a06f1f0f409..b1e54804fc895c95ac8e10eb9a2b80c9d84397a7 100644 --- a/clang/test/CXX/drs/dr25xx.cpp +++ b/clang/test/CXX/drs/dr25xx.cpp @@ -10,6 +10,8 @@ // expected-no-diagnostics #endif +// dr2504 is in dr2504.cpp + namespace dr2516 { // dr2516: 3.0 // NB: reusing 1482 test #if __cplusplus >= 201103L diff --git a/clang/test/CXX/drs/dr292.cpp b/clang/test/CXX/drs/dr292.cpp new file mode 100644 index 0000000000000000000000000000000000000000..19caeef291fa71d356dc2e169cde785afac766e4 --- /dev/null +++ b/clang/test/CXX/drs/dr292.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK + +namespace dr292 { // dr292: 2.9 + +extern int g(); + +struct A { + A(int) throw() {} +}; + +void f() { + new A(g()); +} + +// CHECK-LABEL: define {{.*}} void @dr292::f()() +// CHECK: %[[CALL:.+]] = call {{.*}} @operator new(unsigned long)({{.*}}) +// CHECK: invoke {{.*}} i32 @dr292::g()() +// CHECK-NEXT: to {{.*}} unwind label %lpad +// CHECK-LABEL: lpad: +// CHECK: call void @operator delete(void*)(ptr {{.*}} %[[CALL]]) +// CHECK-LABEL: eh.resume: +// CHECK-LABEL: } + +} // namespace dr292 diff --git a/clang/test/CXX/drs/dr2xx.cpp b/clang/test/CXX/drs/dr2xx.cpp index 1a3ac532f93b267bf2f693c8154001877fcc628c..cbb8734e10c6494a845d238ee21df8c76a4557cb 100644 --- a/clang/test/CXX/drs/dr2xx.cpp +++ b/clang/test/CXX/drs/dr2xx.cpp @@ -26,7 +26,7 @@ namespace dr200 { // dr200: dup 214 } } -// dr201 FIXME: write codegen test +// dr201 is in dr201.cpp namespace dr202 { // dr202: 3.1 template T f(); @@ -76,7 +76,7 @@ namespace dr209 { // dr209: 3.2 }; } -// dr210 FIXME: write codegen test +// dr210 is in dr210.cpp namespace dr211 { // dr211: yes struct A { @@ -1188,7 +1188,7 @@ namespace dr289 { // dr289: yes // dr290: na // dr291: dup 391 -// dr292 FIXME: write a codegen test +// dr292 is in dr292.cpp namespace dr294 { // dr294: no void f() throw(int); diff --git a/clang/test/CXX/over/over.match/over.match.best/p1-2a.cpp b/clang/test/CXX/over/over.match/over.match.best/p1-2a.cpp index dae1ba760cc2035e2b9547a36b47d593f21ebea7..db3e3e3bc85966cc0b86334abfa662f1eabd581b 100644 --- a/clang/test/CXX/over/over.match/over.match.best/p1-2a.cpp +++ b/clang/test/CXX/over/over.match/over.match.best/p1-2a.cpp @@ -97,13 +97,16 @@ namespace non_template static_assert(is_same_v()), int>); // expected-error {{call to 'baz' is ambiguous}} static_assert(is_same_v()), void>); // expected-error {{call to 'bar' is ambiguous}} + // Top-level cv-qualifiers are ignored in template partial ordering per [dcl.fct]/p5. + // After producing the list of parameter types, any top-level cv-qualifiers modifying + // a parameter type are deleted when forming the function type. template - constexpr int goo(int a) requires AtLeast2 && true { // expected-note {{candidate function}} + constexpr int goo(T a) requires AtLeast2 && true { return 1; } template - constexpr int goo(const int b) requires AtLeast2 { // expected-note {{candidate function}} + constexpr int goo(const T b) requires AtLeast2 { return 2; } @@ -122,7 +125,6 @@ namespace non_template return 2; } - // By temp.func.order-6.2.2, this is ambiguous because parameter a and b have different types. - static_assert(goo(1) == 1); // expected-error {{call to 'goo' is ambiguous}} + static_assert(goo(1) == 1); static_assert(doo(2) == 1); } diff --git a/clang/test/CodeGen/LoongArch/atomics.c b/clang/test/CodeGen/LoongArch/atomics.c index edc58d30db186d7f8b028a169653f0951c2eddbc..bd51fea661be1f68e3bf31b705fe356da7948324 100644 --- a/clang/test/CodeGen/LoongArch/atomics.c +++ b/clang/test/CodeGen/LoongArch/atomics.c @@ -11,10 +11,10 @@ void test_i8_atomics(_Atomic(int8_t) * a, int8_t b) { // LA32: load atomic i8, ptr %a seq_cst, align 1 // LA32: store atomic i8 %b, ptr %a seq_cst, align 1 - // LA32: atomicrmw add ptr %a, i8 %b seq_cst + // LA32: atomicrmw add ptr %a, i8 %b seq_cst, align 1 // LA64: load atomic i8, ptr %a seq_cst, align 1 // LA64: store atomic i8 %b, ptr %a seq_cst, align 1 - // LA64: atomicrmw add ptr %a, i8 %b seq_cst + // LA64: atomicrmw add ptr %a, i8 %b seq_cst, align 1 __c11_atomic_load(a, memory_order_seq_cst); __c11_atomic_store(a, b, memory_order_seq_cst); __c11_atomic_fetch_add(a, b, memory_order_seq_cst); @@ -23,22 +23,22 @@ void test_i8_atomics(_Atomic(int8_t) * a, int8_t b) { void test_i32_atomics(_Atomic(int32_t) * a, int32_t b) { // LA32: load atomic i32, ptr %a seq_cst, align 4 // LA32: store atomic i32 %b, ptr %a seq_cst, align 4 - // LA32: atomicrmw add ptr %a, i32 %b seq_cst + // LA32: atomicrmw add ptr %a, i32 %b seq_cst, align 4 // LA64: load atomic i32, ptr %a seq_cst, align 4 // LA64: store atomic i32 %b, ptr %a seq_cst, align 4 - // LA64: atomicrmw add ptr %a, i32 %b seq_cst + // LA64: atomicrmw add ptr %a, i32 %b seq_cst, align 4 __c11_atomic_load(a, memory_order_seq_cst); __c11_atomic_store(a, b, memory_order_seq_cst); __c11_atomic_fetch_add(a, b, memory_order_seq_cst); } void test_i64_atomics(_Atomic(int64_t) * a, int64_t b) { - // LA32: call i64 @__atomic_load_8 - // LA32: call void @__atomic_store_8 - // LA32: call i64 @__atomic_fetch_add_8 + // LA32: load atomic i64, ptr %a seq_cst, align 8 + // LA32: store atomic i64 %b, ptr %a seq_cst, align 8 + // LA32: atomicrmw add ptr %a, i64 %b seq_cst, align 8 // LA64: load atomic i64, ptr %a seq_cst, align 8 // LA64: store atomic i64 %b, ptr %a seq_cst, align 8 - // LA64: atomicrmw add ptr %a, i64 %b seq_cst + // LA64: atomicrmw add ptr %a, i64 %b seq_cst, align 8 __c11_atomic_load(a, memory_order_seq_cst); __c11_atomic_store(a, b, memory_order_seq_cst); __c11_atomic_fetch_add(a, b, memory_order_seq_cst); diff --git a/clang/test/CodeGen/PowerPC/quadword-atomics.c b/clang/test/CodeGen/PowerPC/quadword-atomics.c index bff03b25d27ee9ee846808f33892bcc672d8e5de..dc04423060a03b4f496ac734ec6c99c50f83d9ca 100644 --- a/clang/test/CodeGen/PowerPC/quadword-atomics.c +++ b/clang/test/CodeGen/PowerPC/quadword-atomics.c @@ -1,14 +1,18 @@ // RUN: %clang_cc1 -Werror -Wno-atomic-alignment -triple powerpc64le-linux-gnu \ -// RUN: -target-cpu pwr8 -emit-llvm -o - %s | FileCheck %s --check-prefix=PPC64-QUADWORD-ATOMICS +// RUN: -target-cpu pwr8 -emit-llvm -o - %s | FileCheck %s \ +// RUN: --check-prefixes=PPC64,PPC64-QUADWORD-ATOMICS // RUN: %clang_cc1 -Werror -Wno-atomic-alignment -triple powerpc64le-linux-gnu \ -// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=PPC64 +// RUN: -emit-llvm -o - %s | FileCheck %s \ +// RUN: --check-prefixes=PPC64,PPC64-NO-QUADWORD-ATOMICS // RUN: %clang_cc1 -Werror -Wno-atomic-alignment -triple powerpc64-unknown-aix \ -// RUN: -target-cpu pwr7 -emit-llvm -o - %s | FileCheck %s --check-prefix=PPC64 +// RUN: -target-cpu pwr7 -emit-llvm -o - %s | FileCheck %s \ +// RUN: --check-prefixes=PPC64,PPC64-NO-QUADWORD-ATOMICS // RUN: %clang_cc1 -Werror -Wno-atomic-alignment -triple powerpc64-unknown-aix \ -// RUN: -target-cpu pwr8 -emit-llvm -o - %s | FileCheck %s --check-prefix=PPC64 +// RUN: -target-cpu pwr8 -emit-llvm -o - %s | FileCheck %s \ +// RUN: --check-prefixes=PPC64,PPC64-NO-QUADWORD-ATOMICS // RUN: %clang_cc1 -Werror -Wno-atomic-alignment -triple powerpc64-unknown-aix \ -// RUN: -mabi=quadword-atomics -target-cpu pwr8 -emit-llvm -o - %s | FileCheck %s \ -// RUN: --check-prefix=PPC64-QUADWORD-ATOMICS +// RUN: -mabi=quadword-atomics -target-cpu pwr8 -emit-llvm -o - %s | \ +// RUN: FileCheck %s --check-prefixes=PPC64,PPC64-QUADWORD-ATOMICS typedef struct { @@ -19,66 +23,48 @@ typedef _Atomic(Q) AtomicQ; typedef __int128_t int128_t; -// PPC64-QUADWORD-ATOMICS-LABEL: @test_load( -// PPC64-QUADWORD-ATOMICS: [[TMP3:%.*]] = load atomic i128, ptr [[TMP1:%.*]] acquire, align 16 -// // PPC64-LABEL: @test_load( -// PPC64: call void @__atomic_load(i64 noundef 16, ptr noundef [[TMP3:%.*]], ptr noundef [[TMP4:%.*]], i32 noundef signext 2) +// PPC64: [[TMP3:%.*]] = load atomic i128, ptr [[TMP1:%.*]] acquire, align 16 // Q test_load(AtomicQ *ptr) { // expected-no-diagnostics return __c11_atomic_load(ptr, __ATOMIC_ACQUIRE); } -// PPC64-QUADWORD-ATOMICS-LABEL: @test_store( -// PPC64-QUADWORD-ATOMICS: store atomic i128 [[TMP6:%.*]], ptr [[TMP4:%.*]] release, align 16 -// // PPC64-LABEL: @test_store( -// PPC64: call void @__atomic_store(i64 noundef 16, ptr noundef [[TMP6:%.*]], ptr noundef [[TMP7:%.*]], i32 noundef signext 3) +// PPC64: store atomic i128 [[TMP6:%.*]], ptr [[TMP4:%.*]] release, align 16 // void test_store(Q val, AtomicQ *ptr) { // expected-no-diagnostics __c11_atomic_store(ptr, val, __ATOMIC_RELEASE); } -// PPC64-QUADWORD-ATOMICS-LABEL: @test_add( -// PPC64-QUADWORD-ATOMICS: [[TMP3:%.*]] = atomicrmw add ptr [[TMP0:%.*]], i128 [[TMP2:%.*]] monotonic, align 16 -// // PPC64-LABEL: @test_add( -// PPC64: [[CALL:%.*]] = call i128 @__atomic_fetch_add_16(ptr noundef [[TMP2:%.*]], i128 noundef [[TMP3:%.*]], i32 noundef signext 0) +// PPC64: [[ATOMICRMW:%.*]] = atomicrmw add ptr [[TMP0:%.*]], i128 [[TMP2:%.*]] monotonic, align 16 // void test_add(_Atomic(int128_t) *ptr, int128_t x) { // expected-no-diagnostics __c11_atomic_fetch_add(ptr, x, __ATOMIC_RELAXED); } -// PPC64-QUADWORD-ATOMICS-LABEL: @test_xchg( -// PPC64-QUADWORD-ATOMICS: [[TMP8:%.*]] = atomicrmw xchg ptr [[TMP4:%.*]], i128 [[TMP7:%.*]] seq_cst, align 16 -// // PPC64-LABEL: @test_xchg( -// PPC64: call void @__atomic_exchange(i64 noundef 16, ptr noundef [[TMP7:%.*]], ptr noundef [[TMP8:%.*]], ptr noundef [[TMP9:%.*]], i32 noundef signext 5) +// PPC64: [[TMP8:%.*]] = atomicrmw xchg ptr [[TMP4:%.*]], i128 [[TMP7:%.*]] seq_cst, align 16 // Q test_xchg(AtomicQ *ptr, Q new) { // expected-no-diagnostics return __c11_atomic_exchange(ptr, new, __ATOMIC_SEQ_CST); } -// PPC64-QUADWORD-ATOMICS-LABEL: @test_cmpxchg( -// PPC64-QUADWORD-ATOMICS: [[TMP10:%.*]] = cmpxchg ptr [[TMP5:%.*]], i128 [[TMP8:%.*]], i128 [[TMP9:%.*]] seq_cst monotonic, align 16 -// // PPC64-LABEL: @test_cmpxchg( -// PPC64: [[CALL:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 noundef 16, ptr noundef [[TMP8:%.*]], ptr noundef [[TMP9:%.*]], ptr noundef [[TMP10:%.*]], i32 noundef signext 5, i32 noundef signext 0) +// PPC64: [[TMP10:%.*]] = cmpxchg ptr [[TMP5:%.*]], i128 [[TMP8:%.*]], i128 [[TMP9:%.*]] seq_cst monotonic, align 16 // int test_cmpxchg(AtomicQ *ptr, Q *cmp, Q new) { // expected-no-diagnostics return __c11_atomic_compare_exchange_strong(ptr, cmp, new, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED); } -// PPC64-QUADWORD-ATOMICS-LABEL: @test_cmpxchg_weak( -// PPC64-QUADWORD-ATOMICS: [[TMP10:%.*]] = cmpxchg weak ptr [[TMP5:%.*]], i128 [[TMP8:%.*]], i128 [[TMP9:%.*]] seq_cst monotonic, align 16 -// // PPC64-LABEL: @test_cmpxchg_weak( -// PPC64: [[CALL:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 noundef 16, ptr noundef [[TMP8:%.*]], ptr noundef [[TMP9:%.*]], ptr noundef [[TMP10:%.*]], i32 noundef signext 5, i32 noundef signext 0) +// PPC64: [[TMP10:%.*]] = cmpxchg weak ptr [[TMP5:%.*]], i128 [[TMP8:%.*]], i128 [[TMP9:%.*]] seq_cst monotonic, align 16 // int test_cmpxchg_weak(AtomicQ *ptr, Q *cmp, Q new) { // expected-no-diagnostics @@ -88,8 +74,8 @@ int test_cmpxchg_weak(AtomicQ *ptr, Q *cmp, Q new) { // PPC64-QUADWORD-ATOMICS-LABEL: @is_lock_free( // PPC64-QUADWORD-ATOMICS: ret i32 1 // -// PPC64-LABEL: @is_lock_free( -// PPC64: [[CALL:%.*]] = call zeroext i1 @__atomic_is_lock_free(i64 noundef 16, ptr noundef null) +// PPC64-NO-QUADWORD-ATOMICS-LABEL: @is_lock_free( +// PPC64-NO-QUADWORD-ATOMICS: [[CALL:%.*]] = call zeroext i1 @__atomic_is_lock_free(i64 noundef 16, ptr noundef null) // int is_lock_free() { AtomicQ q; diff --git a/clang/test/CodeGen/RISCV/riscv-atomics.c b/clang/test/CodeGen/RISCV/riscv-atomics.c index f629ad7d72ea821c175e93b65d9201d655087841..437cb949bbb0fea57b553b745fd240156753c364 100644 --- a/clang/test/CodeGen/RISCV/riscv-atomics.c +++ b/clang/test/CodeGen/RISCV/riscv-atomics.c @@ -1,68 +1,34 @@ // RUN: %clang_cc1 -triple riscv32 -O1 -emit-llvm %s -o - \ -// RUN: | FileCheck %s -check-prefix=RV32I +// RUN: -verify=no-atomics // RUN: %clang_cc1 -triple riscv32 -target-feature +a -O1 -emit-llvm %s -o - \ -// RUN: | FileCheck %s -check-prefix=RV32IA +// RUN: -verify=small-atomics // RUN: %clang_cc1 -triple riscv64 -O1 -emit-llvm %s -o - \ -// RUN: | FileCheck %s -check-prefix=RV64I +// RUN: -verify=no-atomics // RUN: %clang_cc1 -triple riscv64 -target-feature +a -O1 -emit-llvm %s -o - \ -// RUN: | FileCheck %s -check-prefix=RV64IA +// RUN: -verify=all-atomics -// This test demonstrates that MaxAtomicInlineWidth is set appropriately when -// the atomics instruction set extension is enabled. +// all-atomics-no-diagnostics #include #include void test_i8_atomics(_Atomic(int8_t) * a, int8_t b) { - // RV32I: call zeroext i8 @__atomic_load_1 - // RV32I: call void @__atomic_store_1 - // RV32I: call zeroext i8 @__atomic_fetch_add_1 - // RV32IA: load atomic i8, ptr %a seq_cst, align 1 - // RV32IA: store atomic i8 %b, ptr %a seq_cst, align 1 - // RV32IA: atomicrmw add ptr %a, i8 %b seq_cst, align 1 - // RV64I: call zeroext i8 @__atomic_load_1 - // RV64I: call void @__atomic_store_1 - // RV64I: call zeroext i8 @__atomic_fetch_add_1 - // RV64IA: load atomic i8, ptr %a seq_cst, align 1 - // RV64IA: store atomic i8 %b, ptr %a seq_cst, align 1 - // RV64IA: atomicrmw add ptr %a, i8 %b seq_cst, align 1 - __c11_atomic_load(a, memory_order_seq_cst); - __c11_atomic_store(a, b, memory_order_seq_cst); - __c11_atomic_fetch_add(a, b, memory_order_seq_cst); + __c11_atomic_load(a, memory_order_seq_cst); // no-atomics-warning {{large atomic operation may incur significant performance penalty; the access size (1 bytes) exceeds the max lock-free size (0 bytes)}} + __c11_atomic_store(a, b, memory_order_seq_cst); // no-atomics-warning {{large atomic operation may incur significant performance penalty; the access size (1 bytes) exceeds the max lock-free size (0 bytes)}} + __c11_atomic_fetch_add(a, b, memory_order_seq_cst); // no-atomics-warning {{large atomic operation may incur significant performance penalty; the access size (1 bytes) exceeds the max lock-free size (0 bytes)}} } void test_i32_atomics(_Atomic(int32_t) * a, int32_t b) { - // RV32I: call i32 @__atomic_load_4 - // RV32I: call void @__atomic_store_4 - // RV32I: call i32 @__atomic_fetch_add_4 - // RV32IA: load atomic i32, ptr %a seq_cst, align 4 - // RV32IA: store atomic i32 %b, ptr %a seq_cst, align 4 - // RV32IA: atomicrmw add ptr %a, i32 %b seq_cst, align 4 - // RV64I: call signext i32 @__atomic_load_4 - // RV64I: call void @__atomic_store_4 - // RV64I: call signext i32 @__atomic_fetch_add_4 - // RV64IA: load atomic i32, ptr %a seq_cst, align 4 - // RV64IA: store atomic i32 %b, ptr %a seq_cst, align 4 - // RV64IA: atomicrmw add ptr %a, i32 %b seq_cst, align 4 - __c11_atomic_load(a, memory_order_seq_cst); - __c11_atomic_store(a, b, memory_order_seq_cst); - __c11_atomic_fetch_add(a, b, memory_order_seq_cst); + __c11_atomic_load(a, memory_order_seq_cst); // no-atomics-warning {{large atomic operation may incur significant performance penalty; the access size (4 bytes) exceeds the max lock-free size (0 bytes)}} + __c11_atomic_store(a, b, memory_order_seq_cst); // no-atomics-warning {{large atomic operation may incur significant performance penalty; the access size (4 bytes) exceeds the max lock-free size (0 bytes)}} + __c11_atomic_fetch_add(a, b, memory_order_seq_cst); // no-atomics-warning {{large atomic operation may incur significant performance penalty; the access size (4 bytes) exceeds the max lock-free size (0 bytes)}} } void test_i64_atomics(_Atomic(int64_t) * a, int64_t b) { - // RV32I: call i64 @__atomic_load_8 - // RV32I: call void @__atomic_store_8 - // RV32I: call i64 @__atomic_fetch_add_8 - // RV32IA: call i64 @__atomic_load_8 - // RV32IA: call void @__atomic_store_8 - // RV32IA: call i64 @__atomic_fetch_add_8 - // RV64I: call i64 @__atomic_load_8 - // RV64I: call void @__atomic_store_8 - // RV64I: call i64 @__atomic_fetch_add_8 - // RV64IA: load atomic i64, ptr %a seq_cst, align 8 - // RV64IA: store atomic i64 %b, ptr %a seq_cst, align 8 - // RV64IA: atomicrmw add ptr %a, i64 %b seq_cst, align 8 - __c11_atomic_load(a, memory_order_seq_cst); - __c11_atomic_store(a, b, memory_order_seq_cst); - __c11_atomic_fetch_add(a, b, memory_order_seq_cst); + __c11_atomic_load(a, memory_order_seq_cst); // no-atomics-warning {{large atomic operation may incur significant performance penalty; the access size (8 bytes) exceeds the max lock-free size (0 bytes)}} + // small-atomics-warning@28 {{large atomic operation may incur significant performance penalty; the access size (8 bytes) exceeds the max lock-free size (4 bytes)}} + __c11_atomic_store(a, b, memory_order_seq_cst); // no-atomics-warning {{large atomic operation may incur significant performance penalty; the access size (8 bytes) exceeds the max lock-free size (0 bytes)}} + // small-atomics-warning@30 {{large atomic operation may incur significant performance penalty; the access size (8 bytes) exceeds the max lock-free size (4 bytes)}} + __c11_atomic_fetch_add(a, b, memory_order_seq_cst); // no-atomics-warning {{large atomic operation may incur significant performance penalty; the access size (8 bytes) exceeds the max lock-free size (0 bytes)}} + // small-atomics-warning@32 {{large atomic operation may incur significant performance penalty; the access size (8 bytes) exceeds the max lock-free size (4 bytes)}} } diff --git a/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i128-8Al.c b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i128-8Al.c index 4f6dcbc2c01ec847b76329f911027a7c73cb27e6..8759df7b19c6388b73cee6bf9ace1f6b46d3f4ed 100644 --- a/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i128-8Al.c +++ b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i128-8Al.c @@ -20,7 +20,8 @@ __int128 Des; // CHECK-LABEL: @f1( // CHECK-NEXT: entry: -// CHECK-NEXT: tail call void @__atomic_load(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull [[AGG_RESULT:%.*]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP0:%.*]] = load atomic i128, ptr @Ptr seq_cst, align 8 +// CHECK-NEXT: store i128 [[TMP0]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2:![0-9]+]] // CHECK-NEXT: ret void // __int128 f1() { @@ -29,8 +30,8 @@ __int128 f1() { // CHECK-LABEL: @f2( // CHECK-NEXT: entry: -// CHECK-NEXT: tail call void @__atomic_load(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull @Ret, i32 noundef signext 5) -// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Ret, align 8, !tbaa [[TBAA2:![0-9]+]] +// CHECK-NEXT: [[TMP0:%.*]] = load atomic i128, ptr @Ptr seq_cst, align 8 +// CHECK-NEXT: store i128 [[TMP0]], ptr @Ret, align 8 // CHECK-NEXT: store i128 [[TMP0]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: ret void // @@ -41,10 +42,8 @@ __int128 f2() { // CHECK-LABEL: @f3( // CHECK-NEXT: entry: -// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[DOTATOMICTMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_store(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull [[DOTATOMICTMP]], i32 noundef signext 5) +// CHECK-NEXT: store atomic i128 [[TMP0]], ptr @Ptr seq_cst, align 8 // CHECK-NEXT: ret void // void f3() { @@ -53,7 +52,8 @@ void f3() { // CHECK-LABEL: @f4( // CHECK-NEXT: entry: -// CHECK-NEXT: tail call void @__atomic_store(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull @Val, i32 noundef signext 5) +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8 +// CHECK-NEXT: store atomic i128 [[TMP0]], ptr @Ptr seq_cst, align 8 // CHECK-NEXT: ret void // void f4() { @@ -62,10 +62,9 @@ void f4() { // CHECK-LABEL: @f5( // CHECK-NEXT: entry: -// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[DOTATOMICTMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_exchange(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull [[DOTATOMICTMP]], ptr noundef nonnull [[AGG_RESULT:%.*]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr @Ptr, i128 [[TMP0]] seq_cst, align 8 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: ret void // __int128 f5() { @@ -74,9 +73,10 @@ __int128 f5() { // CHECK-LABEL: @f6( // CHECK-NEXT: entry: -// CHECK-NEXT: tail call void @__atomic_exchange(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull @Val, ptr noundef nonnull @Ret, i32 noundef signext 5) -// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Ret, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr @Ptr, i128 [[TMP0]] seq_cst, align 8 +// CHECK-NEXT: store i128 [[TMP1]], ptr @Ret, align 8 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: ret void // __int128 f6() { @@ -86,11 +86,17 @@ __int128 f6() { // CHECK-LABEL: @f7( // CHECK-NEXT: entry: -// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Des, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[DOTATOMICTMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: [[CALL:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull @Exp, ptr noundef nonnull [[DOTATOMICTMP]], i32 noundef signext 5, i32 noundef signext 5) -// CHECK-NEXT: ret i1 [[CALL]] +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr @Exp, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = cmpxchg ptr @Ptr, i128 [[TMP1]], i128 [[TMP0]] seq_cst seq_cst, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i128, i1 } [[TMP2]], 1 +// CHECK-NEXT: br i1 [[TMP3]], label [[CMPXCHG_CONTINUE:%.*]], label [[CMPXCHG_STORE_EXPECTED:%.*]] +// CHECK: cmpxchg.store_expected: +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i128, i1 } [[TMP2]], 0 +// CHECK-NEXT: store i128 [[TMP4]], ptr @Exp, align 8 +// CHECK-NEXT: br label [[CMPXCHG_CONTINUE]] +// CHECK: cmpxchg.continue: +// CHECK-NEXT: ret i1 [[TMP3]] // _Bool f7() { return __atomic_compare_exchange_n(&Ptr, &Exp, Des, 0, @@ -99,8 +105,17 @@ _Bool f7() { // CHECK-LABEL: @f8( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL:%.*]] = tail call zeroext i1 @__atomic_compare_exchange(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull @Exp, ptr noundef nonnull @Des, i32 noundef signext 5, i32 noundef signext 5) -// CHECK-NEXT: ret i1 [[CALL]] +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Exp, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr @Des, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = cmpxchg ptr @Ptr, i128 [[TMP0]], i128 [[TMP1]] seq_cst seq_cst, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i128, i1 } [[TMP2]], 1 +// CHECK-NEXT: br i1 [[TMP3]], label [[CMPXCHG_CONTINUE:%.*]], label [[CMPXCHG_STORE_EXPECTED:%.*]] +// CHECK: cmpxchg.store_expected: +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i128, i1 } [[TMP2]], 0 +// CHECK-NEXT: store i128 [[TMP4]], ptr @Exp, align 8 +// CHECK-NEXT: br label [[CMPXCHG_CONTINUE]] +// CHECK: cmpxchg.continue: +// CHECK-NEXT: ret i1 [[TMP3]] // _Bool f8() { return __atomic_compare_exchange(&Ptr, &Exp, &Des, 0, @@ -109,12 +124,8 @@ _Bool f8() { // CHECK-LABEL: @f9( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 -// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_add_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) -// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add ptr @Ptr, i128 [[TMP0]] seq_cst, align 8 // CHECK-NEXT: [[TMP2:%.*]] = add i128 [[TMP1]], [[TMP0]] // CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: ret void @@ -125,12 +136,8 @@ __int128 f9() { // CHECK-LABEL: @f10( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 -// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_sub_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) -// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw sub ptr @Ptr, i128 [[TMP0]] seq_cst, align 8 // CHECK-NEXT: [[TMP2:%.*]] = sub i128 [[TMP1]], [[TMP0]] // CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: ret void @@ -141,12 +148,8 @@ __int128 f10() { // CHECK-LABEL: @f11( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 -// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_and_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) -// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw and ptr @Ptr, i128 [[TMP0]] seq_cst, align 8 // CHECK-NEXT: [[TMP2:%.*]] = and i128 [[TMP1]], [[TMP0]] // CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: ret void @@ -157,12 +160,8 @@ __int128 f11() { // CHECK-LABEL: @f12( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 -// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_xor_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) -// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xor ptr @Ptr, i128 [[TMP0]] seq_cst, align 8 // CHECK-NEXT: [[TMP2:%.*]] = xor i128 [[TMP1]], [[TMP0]] // CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: ret void @@ -173,12 +172,8 @@ __int128 f12() { // CHECK-LABEL: @f13( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 -// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_or_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) -// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw or ptr @Ptr, i128 [[TMP0]] seq_cst, align 8 // CHECK-NEXT: [[TMP2:%.*]] = or i128 [[TMP1]], [[TMP0]] // CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: ret void @@ -189,12 +184,8 @@ __int128 f13() { // CHECK-LABEL: @f14( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 -// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_nand_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) -// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw nand ptr @Ptr, i128 [[TMP0]] seq_cst, align 8 // CHECK-NEXT: [[TMP2:%.*]] = and i128 [[TMP1]], [[TMP0]] // CHECK-NEXT: [[TMP3:%.*]] = xor i128 [[TMP2]], -1 // CHECK-NEXT: store i128 [[TMP3]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] @@ -206,10 +197,9 @@ __int128 f14() { // CHECK-LABEL: @f15( // CHECK-NEXT: entry: -// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_add_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[AGG_RESULT:%.*]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add ptr @Ptr, i128 [[TMP0]] seq_cst, align 8 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: ret void // __int128 f15() { @@ -218,10 +208,9 @@ __int128 f15() { // CHECK-LABEL: @f16( // CHECK-NEXT: entry: -// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_sub_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[AGG_RESULT:%.*]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw sub ptr @Ptr, i128 [[TMP0]] seq_cst, align 8 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: ret void // __int128 f16() { @@ -230,10 +219,9 @@ __int128 f16() { // CHECK-LABEL: @f17( // CHECK-NEXT: entry: -// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_and_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[AGG_RESULT:%.*]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw and ptr @Ptr, i128 [[TMP0]] seq_cst, align 8 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: ret void // __int128 f17() { @@ -242,10 +230,9 @@ __int128 f17() { // CHECK-LABEL: @f18( // CHECK-NEXT: entry: -// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_xor_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[AGG_RESULT:%.*]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xor ptr @Ptr, i128 [[TMP0]] seq_cst, align 8 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: ret void // __int128 f18() { @@ -254,10 +241,9 @@ __int128 f18() { // CHECK-LABEL: @f19( // CHECK-NEXT: entry: -// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_or_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[AGG_RESULT:%.*]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw or ptr @Ptr, i128 [[TMP0]] seq_cst, align 8 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: ret void // __int128 f19() { @@ -266,10 +252,9 @@ __int128 f19() { // CHECK-LABEL: @f20( // CHECK-NEXT: entry: -// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_nand_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[AGG_RESULT:%.*]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw nand ptr @Ptr, i128 [[TMP0]] seq_cst, align 8 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: ret void // __int128 f20() { diff --git a/clang/test/CodeGen/aarch64-ABI-align-packed-assembly.c b/clang/test/CodeGen/aarch64-ABI-align-packed-assembly.c index e6eb98b027bf6b4eaacc19fced61832bf8a2d64b..5ac8fd13891441884aba6a2c14ebb8e6830513cf 100644 --- a/clang/test/CodeGen/aarch64-ABI-align-packed-assembly.c +++ b/clang/test/CodeGen/aarch64-ABI-align-packed-assembly.c @@ -1,5 +1,5 @@ // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -fsyntax-only -triple aarch64-none-eabi -target-feature +neon -S -O2 -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsyntax-only -triple aarch64 -target-feature +neon -S -O2 -o - %s | FileCheck %s #include #include diff --git a/clang/test/CodeGen/aarch64-ABI-align-packed.c b/clang/test/CodeGen/aarch64-ABI-align-packed.c index 03f4834ccd0bc5be3136f37bbd601bec42a15011..93b81d50261bf80dacc3cab82aff06e4c9c0e6c0 100644 --- a/clang/test/CodeGen/aarch64-ABI-align-packed.c +++ b/clang/test/CodeGen/aarch64-ABI-align-packed.c @@ -1,5 +1,5 @@ // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -fsyntax-only -triple aarch64-none-eabi -target-feature +neon -emit-llvm -O2 -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsyntax-only -triple aarch64 -target-feature +neon -emit-llvm -O2 -o - %s | FileCheck %s #include #include diff --git a/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c b/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c index e5d70564d57b304bb6d16a08d6c30cfff4deb9eb..baef74b4c18cc6cb6eb727f38faa5ce0a8fbced2 100644 --- a/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c +++ b/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c @@ -1,8 +1,8 @@ -// RUN: %clang -O3 -target aarch64-linux-eabi %s -S -o- \ +// RUN: %clang -O3 --target=aarch64 %s -S -o- \ // RUN: | FileCheck --check-prefix=CHECK-NO --check-prefix=CHECK %s -// RUN: %clang -O3 -target aarch64-linux-eabi -mfix-cortex-a53-835769 %s -S -o- 2>&1 \ +// RUN: %clang -O3 --target=aarch64 -mfix-cortex-a53-835769 %s -S -o- 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-YES --check-prefix=CHECK %s -// RUN: %clang -O3 -target aarch64-linux-eabi -mno-fix-cortex-a53-835769 %s -S -o- 2>&1 \ +// RUN: %clang -O3 --target=aarch64 -mno-fix-cortex-a53-835769 %s -S -o- 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO --check-prefix=CHECK %s // RUN: %clang -O3 --target=aarch64-linux-androideabi %s -S -o- \ diff --git a/clang/test/CodeGen/aarch64-ls64-inline-asm.c b/clang/test/CodeGen/aarch64-ls64-inline-asm.c index 744d6919b05ee4392aa7d0618aa761361b0b48f9..0ba12ab47ae5cf290d90a427173825c699e3a4e3 100644 --- a/clang/test/CodeGen/aarch64-ls64-inline-asm.c +++ b/clang/test/CodeGen/aarch64-ls64-inline-asm.c @@ -1,5 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple aarch64-eabi -target-feature +ls64 -O1 -S -emit-llvm -x c %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +ls64 -O1 -S -emit-llvm -x c %s -o - | FileCheck %s struct foo { unsigned long long x[8]; }; diff --git a/clang/test/CodeGen/aarch64-ls64.c b/clang/test/CodeGen/aarch64-ls64.c index 8a61a9643dd3deea4acf50df4d0331157da2a8fd..c20be13ed13ce1a4ad38b03f33a0a302a524339a 100644 --- a/clang/test/CodeGen/aarch64-ls64.c +++ b/clang/test/CodeGen/aarch64-ls64.c @@ -1,6 +1,6 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple aarch64-eabi -target-feature +ls64 -S -emit-llvm -x c %s -o - | FileCheck --check-prefixes=CHECK-C %s -// RUN: %clang_cc1 -triple aarch64-eabi -target-feature +ls64 -S -emit-llvm -x c++ %s -o - | FileCheck --check-prefixes=CHECK-CXX %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +ls64 -S -emit-llvm -x c %s -o - | FileCheck --check-prefixes=CHECK-C %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +ls64 -S -emit-llvm -x c++ %s -o - | FileCheck --check-prefixes=CHECK-CXX %s // RUN: %clang_cc1 -triple aarch64_be-eabi -target-feature +ls64 -S -emit-llvm -x c %s -o - | FileCheck --check-prefixes=CHECK-C %s // RUN: %clang_cc1 -triple aarch64_be-eabi -target-feature +ls64 -S -emit-llvm -x c++ %s -o - | FileCheck --check-prefixes=CHECK-CXX %s diff --git a/clang/test/CodeGen/aarch64-matmul.cpp b/clang/test/CodeGen/aarch64-matmul.cpp index 677d8bf9735b003368888a7f89926a0e7f4c642f..58deda1c612c89dc19c37ef4fadaa0c00abae4f9 100644 --- a/clang/test/CodeGen/aarch64-matmul.cpp +++ b/clang/test/CodeGen/aarch64-matmul.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple aarch64-eabi -target-feature +neon -target-feature +i8mm -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +neon -target-feature +i8mm -S -emit-llvm %s -o - | FileCheck %s #ifdef __ARM_FEATURE_MATMUL_INT8 extern "C" void arm_feature_matmulint8_defined() {} diff --git a/clang/test/CodeGen/aarch64-neon-ldst-one-rcpc3.c b/clang/test/CodeGen/aarch64-neon-ldst-one-rcpc3.c index ab7d75292318ce31eeddf835580f26b597150f40..40c5a0a598d68cbb702b7a022d2d3b27df951d71 100644 --- a/clang/test/CodeGen/aarch64-neon-ldst-one-rcpc3.c +++ b/clang/test/CodeGen/aarch64-neon-ldst-one-rcpc3.c @@ -1,5 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple aarch64-arm-none-eabi -target-feature +neon \ +// RUN: %clang_cc1 -triple aarch64 -target-feature +neon \ // RUN: -target-feature +rcpc3 -disable-O0-optnone -emit-llvm -o - %s \ // RUN: | opt -S -passes=mem2reg | FileCheck %s diff --git a/clang/test/CodeGen/aarch64-targetattr-arch.c b/clang/test/CodeGen/aarch64-targetattr-arch.c index 86ddeac0b9e6263fa3de264dcb9a49714131bfd6..ed731d0378625d635326e55350cd40fa9f604418 100644 --- a/clang/test/CodeGen/aarch64-targetattr-arch.c +++ b/clang/test/CodeGen/aarch64-targetattr-arch.c @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -triple aarch64-eabi -target-feature +v8a -verify -DHAS8 -S %s -o - -// RUN: %clang_cc1 -triple aarch64-eabi -target-feature +v8.1a -verify -DHAS81 -S %s -o - -// RUN: %clang_cc1 -triple aarch64-eabi -target-feature +v9a -verify -DHAS9 -S %s -o - +// RUN: %clang_cc1 -triple aarch64 -target-feature +v8a -verify -DHAS8 -S %s -o - +// RUN: %clang_cc1 -triple aarch64 -target-feature +v8.1a -verify -DHAS81 -S %s -o - +// RUN: %clang_cc1 -triple aarch64 -target-feature +v9a -verify -DHAS9 -S %s -o - // REQUIRES: aarch64-registered-target #ifdef HAS9 diff --git a/clang/test/CodeGen/aarch64-targetattr-crypto.c b/clang/test/CodeGen/aarch64-targetattr-crypto.c index d3609240fbd55bcc17827bff7bf7fe4c5f656ba1..006a394be77753725c19980a56fd592fdc2898f8 100644 --- a/clang/test/CodeGen/aarch64-targetattr-crypto.c +++ b/clang/test/CodeGen/aarch64-targetattr-crypto.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple aarch64-eabi -target-feature +v8a -verify -S %s -o - +// RUN: %clang_cc1 -triple aarch64 -target-feature +v8a -verify -S %s -o - // REQUIRES: aarch64-registered-target #include diff --git a/clang/test/CodeGen/aarch64-targetattr.c b/clang/test/CodeGen/aarch64-targetattr.c index 1a3a84a73dbad196a811b97c9bc4530c59bfc593..bf4c1476d8815a9c091919bec3c95fd4936acfb9 100644 --- a/clang/test/CodeGen/aarch64-targetattr.c +++ b/clang/test/CodeGen/aarch64-targetattr.c @@ -1,5 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple aarch64-eabi -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple aarch64 -S -emit-llvm %s -o - | FileCheck %s // CHECK-LABEL: @v82() #0 __attribute__((target("arch=armv8.2-a"))) diff --git a/clang/test/CodeGen/aarch64-tme.cpp b/clang/test/CodeGen/aarch64-tme.cpp index 5004751cb30062d858021aedc548c7d46516462a..096a8e4248f645130ea5ed16cf418e1082cfc046 100644 --- a/clang/test/CodeGen/aarch64-tme.cpp +++ b/clang/test/CodeGen/aarch64-tme.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple aarch64-eabi -target-feature +tme -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -DUSE_ACLE -triple aarch64-eabi -target-feature +tme -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +tme -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -DUSE_ACLE -triple aarch64 -target-feature +tme -S -emit-llvm %s -o - | FileCheck %s #define A -1 constexpr int f() { return 65536; } diff --git a/clang/test/CodeGen/arm-atomics-m.c b/clang/test/CodeGen/arm-atomics-m.c index b9cc72bc6b98aba0a105aef9efc887e4e6b074d1..6087fd9d6a66ae286887ce188936aadd4045a328 100644 --- a/clang/test/CodeGen/arm-atomics-m.c +++ b/clang/test/CodeGen/arm-atomics-m.c @@ -22,14 +22,14 @@ void test_presence(void) r = 0; __atomic_store(&i, &r, memory_order_seq_cst); - // CHECK: __atomic_fetch_add_8 + // CHECK: atomicrmw add ptr {{.*}} seq_cst, align 8 __atomic_fetch_add(&l, 1, memory_order_seq_cst); - // CHECK: __atomic_fetch_sub_8 + // CHECK: atomicrmw sub ptr {{.*}} seq_cst, align 8 __atomic_fetch_sub(&l, 1, memory_order_seq_cst); - // CHECK: __atomic_load_8 + // CHECK: load atomic i64, ptr {{.*}} seq_cst, align 8 long long rl; __atomic_load(&l, &rl, memory_order_seq_cst); - // CHECK: __atomic_store_8 + // CHECK: store atomic i64 {{.*}}, ptr {{.*}} seq_cst, align 8 rl = 0; __atomic_store(&l, &rl, memory_order_seq_cst); } diff --git a/clang/test/CodeGen/arm-atomics-m0.c b/clang/test/CodeGen/arm-atomics-m0.c index 335a1d2711f808773b849b8e8f563e793a4f7f78..94e344cf608df42128b474ff3d0347f9dcf3bc4e 100644 --- a/clang/test/CodeGen/arm-atomics-m0.c +++ b/clang/test/CodeGen/arm-atomics-m0.c @@ -11,25 +11,25 @@ typedef enum memory_order { void test_presence(void) { // CHECK-LABEL: @test_presence - // CHECK: __atomic_fetch_add_4 + // CHECK: atomicrmw add ptr {{.*}} seq_cst, align 4 __atomic_fetch_add(&i, 1, memory_order_seq_cst); - // CHECK: __atomic_fetch_sub_4 + // CHECK: atomicrmw sub {{.*}} seq_cst, align 4 __atomic_fetch_sub(&i, 1, memory_order_seq_cst); - // CHECK: __atomic_load_4 + // CHECK: load atomic i32, ptr {{.*}} seq_cst, align 4 int r; __atomic_load(&i, &r, memory_order_seq_cst); - // CHECK: __atomic_store_4 + // CHECK: store atomic i32 {{.*}}, ptr {{.*}} seq_cst, align 4 r = 0; __atomic_store(&i, &r, memory_order_seq_cst); - // CHECK: __atomic_fetch_add_8 + // CHECK: atomicrmw add {{.*}} seq_cst, align 8 __atomic_fetch_add(&l, 1, memory_order_seq_cst); - // CHECK: __atomic_fetch_sub_8 + // CHECK: atomicrmw sub {{.*}} seq_cst, align 8 __atomic_fetch_sub(&l, 1, memory_order_seq_cst); - // CHECK: __atomic_load_8 + // CHECK: load atomic i64, ptr {{.*}} seq_cst, align 8 long long rl; __atomic_load(&l, &rl, memory_order_seq_cst); - // CHECK: __atomic_store_8 + // CHECK: store atomic i64 {{.*}}, ptr {{.*}} seq_cst, align 8 rl = 0; __atomic_store(&l, &rl, memory_order_seq_cst); } diff --git a/clang/test/CodeGen/arm64-mte.c b/clang/test/CodeGen/arm64-mte.c index 1c65d6a626dda20ddc1a9959f540eb9141b37443..7dde23cfd8e7b424a5808d9df025a0b27f56ea77 100644 --- a/clang/test/CodeGen/arm64-mte.c +++ b/clang/test/CodeGen/arm64-mte.c @@ -1,6 +1,6 @@ // Test memory tagging extension intrinsics -// RUN: %clang_cc1 -triple aarch64-none-linux-eabi -target-feature +mte -O3 -S -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple aarch64-none-linux-eabi -DMTE -O3 -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +mte -O3 -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64 -DMTE -O3 -S -emit-llvm -o - %s | FileCheck %s #include #include diff --git a/clang/test/CodeGen/atomic-ops-libcall.c b/clang/test/CodeGen/atomic-ops-libcall.c index 745ccd22bf33f0ac1537c89857c248dba579b2c6..38a23f7236ce72882961d69d7724c95c28661333 100644 --- a/clang/test/CodeGen/atomic-ops-libcall.c +++ b/clang/test/CodeGen/atomic-ops-libcall.c @@ -1,120 +1,338 @@ -// RUN: %clang_cc1 < %s -triple armv5e-none-linux-gnueabi -emit-llvm -O1 | FileCheck %s - -// FIXME: This file should not be checking -O1 output. -// Ie, it is testing many IR optimizer passes as part of front-end verification. +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// RUN: %clang_cc1 -triple armv5e-none-linux-gnueabi -emit-llvm %s -o - | FileCheck %s enum memory_order { memory_order_relaxed, memory_order_consume, memory_order_acquire, memory_order_release, memory_order_acq_rel, memory_order_seq_cst }; +// CHECK-LABEL: define dso_local ptr @test_c11_atomic_fetch_add_int_ptr( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 12, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw add ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret ptr [[TMP3]] +// int *test_c11_atomic_fetch_add_int_ptr(_Atomic(int *) *p) { - // CHECK: test_c11_atomic_fetch_add_int_ptr - // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_add_4(ptr noundef %p, i32 noundef 12, i32 noundef 5) return __c11_atomic_fetch_add(p, 3, memory_order_seq_cst); } +// CHECK-LABEL: define dso_local ptr @test_c11_atomic_fetch_sub_int_ptr( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 20, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw sub ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret ptr [[TMP3]] +// int *test_c11_atomic_fetch_sub_int_ptr(_Atomic(int *) *p) { - // CHECK: test_c11_atomic_fetch_sub_int_ptr - // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_sub_4(ptr noundef %p, i32 noundef 20, i32 noundef 5) return __c11_atomic_fetch_sub(p, 5, memory_order_seq_cst); } +// CHECK-LABEL: define dso_local i32 @test_c11_atomic_fetch_add_int( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 3, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw add ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret i32 [[TMP3]] +// int test_c11_atomic_fetch_add_int(_Atomic(int) *p) { - // CHECK: test_c11_atomic_fetch_add_int - // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_add_4(ptr noundef %p, i32 noundef 3, i32 noundef 5) return __c11_atomic_fetch_add(p, 3, memory_order_seq_cst); } +// CHECK-LABEL: define dso_local i32 @test_c11_atomic_fetch_sub_int( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 5, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw sub ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret i32 [[TMP3]] +// int test_c11_atomic_fetch_sub_int(_Atomic(int) *p) { - // CHECK: test_c11_atomic_fetch_sub_int - // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_sub_4(ptr noundef %p, i32 noundef 5, i32 noundef 5) return __c11_atomic_fetch_sub(p, 5, memory_order_seq_cst); } +// CHECK-LABEL: define dso_local ptr @fp2a( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 4, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw sub ptr [[TMP0]], i32 [[TMP1]] monotonic, align 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret ptr [[TMP3]] +// int *fp2a(int **p) { - // CHECK: @fp2a - // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_sub_4(ptr noundef %p, i32 noundef 4, i32 noundef 0) // Note, the GNU builtins do not multiply by sizeof(T)! return __atomic_fetch_sub(p, 4, memory_order_relaxed); } +// CHECK-LABEL: define dso_local i32 @test_atomic_fetch_add( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 55, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw add ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret i32 [[TMP3]] +// int test_atomic_fetch_add(int *p) { - // CHECK: test_atomic_fetch_add - // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_add_4(ptr noundef %p, i32 noundef 55, i32 noundef 5) return __atomic_fetch_add(p, 55, memory_order_seq_cst); } +// CHECK-LABEL: define dso_local i32 @test_atomic_fetch_sub( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 55, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw sub ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret i32 [[TMP3]] +// int test_atomic_fetch_sub(int *p) { - // CHECK: test_atomic_fetch_sub - // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_sub_4(ptr noundef %p, i32 noundef 55, i32 noundef 5) return __atomic_fetch_sub(p, 55, memory_order_seq_cst); } +// CHECK-LABEL: define dso_local i32 @test_atomic_fetch_and( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 55, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw and ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret i32 [[TMP3]] +// int test_atomic_fetch_and(int *p) { - // CHECK: test_atomic_fetch_and - // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_and_4(ptr noundef %p, i32 noundef 55, i32 noundef 5) return __atomic_fetch_and(p, 55, memory_order_seq_cst); } +// CHECK-LABEL: define dso_local i32 @test_atomic_fetch_or( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 55, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw or ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret i32 [[TMP3]] +// int test_atomic_fetch_or(int *p) { - // CHECK: test_atomic_fetch_or - // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_or_4(ptr noundef %p, i32 noundef 55, i32 noundef 5) return __atomic_fetch_or(p, 55, memory_order_seq_cst); } +// CHECK-LABEL: define dso_local i32 @test_atomic_fetch_xor( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 55, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw xor ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret i32 [[TMP3]] +// int test_atomic_fetch_xor(int *p) { - // CHECK: test_atomic_fetch_xor - // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_xor_4(ptr noundef %p, i32 noundef 55, i32 noundef 5) return __atomic_fetch_xor(p, 55, memory_order_seq_cst); } +// CHECK-LABEL: define dso_local i32 @test_atomic_fetch_nand( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 55, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw nand ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret i32 [[TMP3]] +// int test_atomic_fetch_nand(int *p) { - // CHECK: test_atomic_fetch_nand - // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_nand_4(ptr noundef %p, i32 noundef 55, i32 noundef 5) return __atomic_fetch_nand(p, 55, memory_order_seq_cst); } +// CHECK-LABEL: define dso_local i32 @test_atomic_add_fetch( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 55, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw add ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: [[TMP3:%.*]] = add i32 [[TMP2]], [[TMP1]] +// CHECK-NEXT: store i32 [[TMP3]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret i32 [[TMP4]] +// int test_atomic_add_fetch(int *p) { - // CHECK: test_atomic_add_fetch - // CHECK: [[CALL:%[^ ]*]] = tail call i32 @__atomic_fetch_add_4(ptr noundef %p, i32 noundef 55, i32 noundef 5) - // CHECK: {{%[^ ]*}} = add i32 [[CALL]], 55 return __atomic_add_fetch(p, 55, memory_order_seq_cst); } +// CHECK-LABEL: define dso_local i32 @test_atomic_sub_fetch( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 55, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw sub ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: [[TMP3:%.*]] = sub i32 [[TMP2]], [[TMP1]] +// CHECK-NEXT: store i32 [[TMP3]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret i32 [[TMP4]] +// int test_atomic_sub_fetch(int *p) { - // CHECK: test_atomic_sub_fetch - // CHECK: [[CALL:%[^ ]*]] = tail call i32 @__atomic_fetch_sub_4(ptr noundef %p, i32 noundef 55, i32 noundef 5) - // CHECK: {{%[^ ]*}} = add i32 [[CALL]], -55 return __atomic_sub_fetch(p, 55, memory_order_seq_cst); } +// CHECK-LABEL: define dso_local i32 @test_atomic_and_fetch( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 55, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw and ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], [[TMP1]] +// CHECK-NEXT: store i32 [[TMP3]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret i32 [[TMP4]] +// int test_atomic_and_fetch(int *p) { - // CHECK: test_atomic_and_fetch - // CHECK: [[CALL:%[^ ]*]] = tail call i32 @__atomic_fetch_and_4(ptr noundef %p, i32 noundef 55, i32 noundef 5) - // CHECK: {{%[^ ]*}} = and i32 [[CALL]], 55 return __atomic_and_fetch(p, 55, memory_order_seq_cst); } +// CHECK-LABEL: define dso_local i32 @test_atomic_or_fetch( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 55, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw or ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: [[TMP3:%.*]] = or i32 [[TMP2]], [[TMP1]] +// CHECK-NEXT: store i32 [[TMP3]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret i32 [[TMP4]] +// int test_atomic_or_fetch(int *p) { - // CHECK: test_atomic_or_fetch - // CHECK: [[CALL:%[^ ]*]] = tail call i32 @__atomic_fetch_or_4(ptr noundef %p, i32 noundef 55, i32 noundef 5) - // CHECK: {{%[^ ]*}} = or i32 [[CALL]], 55 return __atomic_or_fetch(p, 55, memory_order_seq_cst); } +// CHECK-LABEL: define dso_local i32 @test_atomic_xor_fetch( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 55, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw xor ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], [[TMP1]] +// CHECK-NEXT: store i32 [[TMP3]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret i32 [[TMP4]] +// int test_atomic_xor_fetch(int *p) { - // CHECK: test_atomic_xor_fetch - // CHECK: [[CALL:%[^ ]*]] = tail call i32 @__atomic_fetch_xor_4(ptr noundef %p, i32 noundef 55, i32 noundef 5) - // CHECK: {{%[^ ]*}} = xor i32 [[CALL]], 55 return __atomic_xor_fetch(p, 55, memory_order_seq_cst); } +// CHECK-LABEL: define dso_local i32 @test_atomic_nand_fetch( +// CHECK-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 4 +// CHECK-NEXT: store i32 55, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw nand ptr [[TMP0]], i32 [[TMP1]] seq_cst, align 4 +// CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], [[TMP1]] +// CHECK-NEXT: [[TMP4:%.*]] = xor i32 [[TMP3]], -1 +// CHECK-NEXT: store i32 [[TMP4]], ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[ATOMIC_TEMP]], align 4 +// CHECK-NEXT: ret i32 [[TMP5]] +// int test_atomic_nand_fetch(int *p) { - // CHECK: test_atomic_nand_fetch - // CHECK: [[CALL:%[^ ]*]] = tail call i32 @__atomic_fetch_nand_4(ptr noundef %p, i32 noundef 55, i32 noundef 5) - // FIXME: We should not be checking optimized IR. It changes independently of clang. - // FIXME-CHECK: [[AND:%[^ ]*]] = and i32 [[CALL]], 55 - // FIXME-CHECK: {{%[^ ]*}} = xor i32 [[AND]], -1 return __atomic_nand_fetch(p, 55, memory_order_seq_cst); } diff --git a/clang/test/CodeGen/atomic-ops.c b/clang/test/CodeGen/atomic-ops.c index 9ac05d270b97c5a3163ac0750ca46a0becad0824..b6060dcc540f9059ff03386001ceca4280d9150f 100644 --- a/clang/test/CodeGen/atomic-ops.c +++ b/clang/test/CodeGen/atomic-ops.c @@ -198,7 +198,8 @@ struct S implicit_load(_Atomic(struct S) *a) { struct S fd1(struct S *a) { // CHECK-LABEL: @fd1 // CHECK: [[RETVAL:%.*]] = alloca %struct.S, align 4 - // CHECK: call void @__atomic_load(i32 noundef 8, ptr noundef {{.*}}, ptr noundef [[RETVAL]], i32 noundef 5) + // CHECK: [[TMP1:%.*]] = load atomic i64, ptr {{%.*}} seq_cst, align 4 + // CHECK-NEXT: store i64 [[TMP1]], ptr [[RETVAL]], align 4 // CHECK: ret struct S ret; __atomic_load(a, &ret, memory_order_seq_cst); @@ -213,7 +214,8 @@ void fd2(struct S *a, struct S *b) { // CHECK-NEXT: store ptr %b, ptr [[B_ADDR]], align 4 // CHECK-NEXT: [[LOAD_A_PTR:%.*]] = load ptr, ptr [[A_ADDR]], align 4 // CHECK-NEXT: [[LOAD_B_PTR:%.*]] = load ptr, ptr [[B_ADDR]], align 4 - // CHECK-NEXT: call void @__atomic_store(i32 noundef 8, ptr noundef [[LOAD_A_PTR]], ptr noundef [[LOAD_B_PTR]], + // CHECK-NEXT: [[LOAD_B:%.*]] = load i64, ptr [[LOAD_B_PTR]], align 4 + // CHECK-NEXT: store atomic i64 [[LOAD_B]], ptr [[LOAD_A_PTR]] seq_cst, align 4 // CHECK-NEXT: ret void __atomic_store(a, b, memory_order_seq_cst); } @@ -229,7 +231,9 @@ void fd3(struct S *a, struct S *b, struct S *c) { // CHECK-NEXT: [[LOAD_A_PTR:%.*]] = load ptr, ptr [[A_ADDR]], align 4 // CHECK-NEXT: [[LOAD_B_PTR:%.*]] = load ptr, ptr [[B_ADDR]], align 4 // CHECK-NEXT: [[LOAD_C_PTR:%.*]] = load ptr, ptr [[C_ADDR]], align 4 - // CHECK-NEXT: call void @__atomic_exchange(i32 noundef 8, ptr noundef [[LOAD_A_PTR]], ptr noundef [[LOAD_B_PTR]], ptr noundef [[LOAD_C_PTR]], + // CHECK-NEXT: [[LOAD_B:%.*]] = load i64, ptr [[LOAD_B_PTR]], align 4 + // CHECK-NEXT: [[RESULT:%.*]] = atomicrmw xchg ptr [[LOAD_A_PTR]], i64 [[LOAD_B]] seq_cst, align 4 + // CHECK-NEXT: store i64 [[RESULT]], ptr [[LOAD_C_PTR]], align 4 __atomic_exchange(a, b, c, memory_order_seq_cst); } @@ -245,8 +249,9 @@ _Bool fd4(struct S *a, struct S *b, struct S *c) { // CHECK-NEXT: [[LOAD_A_PTR:%.*]] = load ptr, ptr [[A_ADDR]], align 4 // CHECK-NEXT: [[LOAD_B_PTR:%.*]] = load ptr, ptr [[B_ADDR]], align 4 // CHECK-NEXT: [[LOAD_C_PTR:%.*]] = load ptr, ptr [[C_ADDR]], align 4 - // CHECK-NEXT: [[CALL:%.*]] = call zeroext i1 @__atomic_compare_exchange(i32 noundef 8, ptr noundef [[LOAD_A_PTR]], ptr noundef [[LOAD_B_PTR]], ptr noundef [[LOAD_C_PTR]], - // CHECK-NEXT: ret i1 [[CALL]] + // CHECK-NEXT: [[LOAD_B:%.*]] = load i64, ptr [[LOAD_B_PTR]], align 4 + // CHECK-NEXT: [[LOAD_C:%.*]] = load i64, ptr [[LOAD_C_PTR]], align 4 + // CHECK-NEXT: {{.*}} = cmpxchg weak ptr [[LOAD_A_PTR]], i64 [[LOAD_B]], i64 [[LOAD_C]] seq_cst seq_cst, align 4 return __atomic_compare_exchange(a, b, c, 1, 5, 5); } @@ -682,13 +687,13 @@ void test_underaligned(void) { // CHECK-LABEL: @test_underaligned struct Underaligned { char c[8]; } underaligned_a, underaligned_b, underaligned_c; - // CHECK: call void @__atomic_load(i32 noundef 8, + // CHECK: load atomic i64, {{.*}}, align 1 __atomic_load(&underaligned_a, &underaligned_b, memory_order_seq_cst); - // CHECK: call void @__atomic_store(i32 noundef 8, + // CHECK: store atomic i64 {{.*}}, align 1 __atomic_store(&underaligned_a, &underaligned_b, memory_order_seq_cst); - // CHECK: call void @__atomic_exchange(i32 noundef 8, + // CHECK: atomicrmw xchg ptr {{.*}}, align 1 __atomic_exchange(&underaligned_a, &underaligned_b, &underaligned_c, memory_order_seq_cst); - // CHECK: call {{.*}} @__atomic_compare_exchange(i32 noundef 8, + // CHECK: cmpxchg weak ptr {{.*}}, align 1 __atomic_compare_exchange(&underaligned_a, &underaligned_b, &underaligned_c, 1, memory_order_seq_cst, memory_order_seq_cst); __attribute__((aligned)) struct Underaligned aligned_a, aligned_b, aligned_c; @@ -747,7 +752,7 @@ void test_minmax_postop(int *si, unsigned *ui, unsigned short *us, signed char * // CHECK: [[NEW:%.*]] = select i1 [[TST]], i32 [[OLD]], i32 [[RHS]] // CHECK: store i32 [[NEW]], ptr *si = __atomic_min_fetch(si, 42, memory_order_release); - + // CHECK: [[OLD:%.*]] = atomicrmw umax ptr [[PTR:%.*]], i32 [[RHS:%.*]] release, align 4 // CHECK: [[TST:%.*]] = icmp ugt i32 [[OLD]], [[RHS]] // CHECK: [[NEW:%.*]] = select i1 [[TST]], i32 [[OLD]], i32 [[RHS]] @@ -772,7 +777,7 @@ void test_minmax_postop(int *si, unsigned *ui, unsigned short *us, signed char * // CHECK: store i8 [[NEW]], ptr *sc = __atomic_min_fetch(sc, 42, memory_order_release); - // CHECK: [[OLD:%.*]] = call i64 @__atomic_fetch_umin_8(ptr noundef {{%.*}}, i64 noundef [[RHS:%.*]], + // CHECK: [[OLD:%.*]] = atomicrmw umin ptr {{%.*}}, i64 [[RHS:%.*]] release, align 4 // CHECK: [[TST:%.*]] = icmp ult i64 [[OLD]], [[RHS]] // CHECK: [[NEW:%.*]] = select i1 [[TST]], i64 [[OLD]], i64 [[RHS]] // CHECK: store i64 [[NEW]], ptr diff --git a/clang/test/CodeGen/atomics-inlining.c b/clang/test/CodeGen/atomics-inlining.c index 862c63076b2dc0aba3c9b7a5dd854629a53812b8..217a294ee84abc4a72f895dde1e015c85d3b3fd9 100644 --- a/clang/test/CodeGen/atomics-inlining.c +++ b/clang/test/CodeGen/atomics-inlining.c @@ -38,14 +38,14 @@ void test1(void) { (void)__atomic_store(&a1, &a2, memory_order_seq_cst); // ARM-LABEL: define{{.*}} void @test1 -// ARM: = call{{.*}} zeroext i8 @__atomic_load_1(ptr noundef @c1 -// ARM: call{{.*}} void @__atomic_store_1(ptr noundef @c1, i8 noundef zeroext -// ARM: = call{{.*}} zeroext i16 @__atomic_load_2(ptr noundef @s1 -// ARM: call{{.*}} void @__atomic_store_2(ptr noundef @s1, i16 noundef zeroext -// ARM: = call{{.*}} i32 @__atomic_load_4(ptr noundef @i1 -// ARM: call{{.*}} void @__atomic_store_4(ptr noundef @i1, i32 noundef -// ARM: = call{{.*}} i64 @__atomic_load_8(ptr noundef @ll1 -// ARM: call{{.*}} void @__atomic_store_8(ptr noundef @ll1, i64 noundef +// ARM: = load atomic i8, ptr @c1 seq_cst, align 1 +// ARM: store atomic i8 {{.*}}, ptr @c1 seq_cst, align 1 +// ARM: = load atomic i16, ptr @s1 seq_cst, align 2 +// ARM: store atomic i16 {{.*}}, ptr @s1 seq_cst, align 2 +// ARM: = load atomic i32, ptr @i1 seq_cst, align 4 +// ARM: store atomic i32 {{.*}}, ptr @i1 seq_cst, align 4 +// ARM: = load atomic i64, ptr @ll1 seq_cst, align 8 +// ARM: store atomic i64 {{.*}}, ptr @ll1 seq_cst, align 8 // ARM: call{{.*}} void @__atomic_load(i32 noundef 100, ptr noundef @a1, ptr noundef @a2 // ARM: call{{.*}} void @__atomic_store(i32 noundef 100, ptr noundef @a1, ptr noundef @a2 @@ -56,8 +56,8 @@ void test1(void) { // PPC32: store atomic i16 {{.*}}, ptr @s1 seq_cst, align 2 // PPC32: = load atomic i32, ptr @i1 seq_cst, align 4 // PPC32: store atomic i32 {{.*}}, ptr @i1 seq_cst, align 4 -// PPC32: = call i64 @__atomic_load_8(ptr noundef @ll1 -// PPC32: call void @__atomic_store_8(ptr noundef @ll1, i64 +// PPC32: = load atomic i64, ptr @ll1 seq_cst, align 8 +// PPC32: store atomic i64 {{.*}}, ptr @ll1 seq_cst, align 8 // PPC32: call void @__atomic_load(i32 noundef 100, ptr noundef @a1, ptr noundef @a2 // PPC32: call void @__atomic_store(i32 noundef 100, ptr noundef @a1, ptr noundef @a2 @@ -80,8 +80,8 @@ void test1(void) { // MIPS32: store atomic i16 {{.*}}, ptr @s1 seq_cst, align 2 // MIPS32: = load atomic i32, ptr @i1 seq_cst, align 4 // MIPS32: store atomic i32 {{.*}}, ptr @i1 seq_cst, align 4 -// MIPS32: call i64 @__atomic_load_8(ptr noundef @ll1 -// MIPS32: call void @__atomic_store_8(ptr noundef @ll1, i64 +// MIPS32: = load atomic i64, ptr @ll1 seq_cst, align 8 +// MIPS32: store atomic i64 {{.*}}, ptr @ll1 seq_cst, align 8 // MIPS32: call void @__atomic_load(i32 noundef signext 100, ptr noundef @a1, ptr noundef @a2 // MIPS32: call void @__atomic_store(i32 noundef signext 100, ptr noundef @a1, ptr noundef @a2 @@ -94,7 +94,7 @@ void test1(void) { // MIPS64: store atomic i32 {{.*}}, ptr @i1 seq_cst, align 4 // MIPS64: = load atomic i64, ptr @ll1 seq_cst, align 8 // MIPS64: store atomic i64 {{.*}}, ptr @ll1 seq_cst, align 8 -// MIPS64: call void @__atomic_load(i64 noundef zeroext 100, ptr noundef @a1 +// MIPS64: call void @__atomic_load(i64 noundef zeroext 100, ptr noundef @a1, ptr noundef @a2 // MIPS64: call void @__atomic_store(i64 noundef zeroext 100, ptr noundef @a1, ptr noundef @a2 // SPARC-LABEL: define{{.*}} void @test1 @@ -104,12 +104,12 @@ void test1(void) { // SPARC: store atomic i16 {{.*}}, ptr @s1 seq_cst, align 2 // SPARC: = load atomic i32, ptr @i1 seq_cst, align 4 // SPARC: store atomic i32 {{.*}}, ptr @i1 seq_cst, align 4 -// SPARCV8: call i64 @__atomic_load_8(ptr noundef @ll1 -// SPARCV8: call void @__atomic_store_8(ptr noundef @ll1, i64 -// SPARCV9: load atomic i64, ptr @ll1 seq_cst, align 8 -// SPARCV9: store atomic i64 {{.*}}, ptr @ll1 seq_cst, align 8 +// SPARC: load atomic i64, ptr @ll1 seq_cst, align 8 +// SPARC: store atomic i64 {{.*}}, ptr @ll1 seq_cst, align 8 // SPARCV8: call void @__atomic_load(i32 noundef 100, ptr noundef @a1, ptr noundef @a2 // SPARCV8: call void @__atomic_store(i32 noundef 100, ptr noundef @a1, ptr noundef @a2 +// SPARCV9: call void @__atomic_load(i64 noundef 100, ptr noundef @a1, ptr noundef @a2 +// SPARCV9: call void @__atomic_store(i64 noundef 100, ptr noundef @a1, ptr noundef @a2 // NVPTX-LABEL: define{{.*}} void @test1 // NVPTX: = load atomic i8, ptr @c1 seq_cst, align 1 @@ -120,7 +120,7 @@ void test1(void) { // NVPTX: store atomic i32 {{.*}}, ptr @i1 seq_cst, align 4 // NVPTX: = load atomic i64, ptr @ll1 seq_cst, align 8 // NVPTX: store atomic i64 {{.*}}, ptr @ll1 seq_cst, align 8 -// NVPTX: call void @__atomic_load(i64 noundef 100, ptr noundef @a1, ptr noundef @a2, i32 noundef 5) -// NVPTX: call void @__atomic_store(i64 noundef 100, ptr noundef @a1, ptr noundef @a2, i32 noundef 5) +// NVPTX: call void @__atomic_load(i64 noundef 100, ptr noundef @a1, ptr noundef @a2 +// NVPTX: call void @__atomic_store(i64 noundef 100, ptr noundef @a1, ptr noundef @a2 } diff --git a/clang/test/CodeGen/attr-riscv-rvv-vector-bits-bitcast.c b/clang/test/CodeGen/attr-riscv-rvv-vector-bits-bitcast.c index a7b3123e61cd520e505aaf4b4481915802989fdb..20fb4a04564c755efb41d449aa77977db5c4804b 100644 --- a/clang/test/CodeGen/attr-riscv-rvv-vector-bits-bitcast.c +++ b/clang/test/CodeGen/attr-riscv-rvv-vector-bits-bitcast.c @@ -177,29 +177,26 @@ void write_float64m1(struct struct_float64m1 *s, vfloat64m1_t x) { // CHECK-64-LABEL: @read_bool1( // CHECK-64-NEXT: entry: -// CHECK-64-NEXT: [[SAVED_VALUE:%.*]] = alloca <8 x i8>, align 8 // CHECK-64-NEXT: [[Y:%.*]] = getelementptr inbounds i8, ptr [[S:%.*]], i64 8 // CHECK-64-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr [[Y]], align 8, !tbaa [[TBAA4]] -// CHECK-64-NEXT: store <8 x i8> [[TMP0]], ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA4]] -// CHECK-64-NEXT: [[TMP1:%.*]] = load , ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA4]] +// CHECK-64-NEXT: [[CAST_SCALABLE:%.*]] = tail call @llvm.vector.insert.nxv8i8.v8i8( undef, <8 x i8> [[TMP0]], i64 0) +// CHECK-64-NEXT: [[TMP1:%.*]] = bitcast [[CAST_SCALABLE]] to // CHECK-64-NEXT: ret [[TMP1]] // // CHECK-128-LABEL: @read_bool1( // CHECK-128-NEXT: entry: -// CHECK-128-NEXT: [[SAVED_VALUE:%.*]] = alloca <16 x i8>, align 16 // CHECK-128-NEXT: [[Y:%.*]] = getelementptr inbounds i8, ptr [[S:%.*]], i64 16 // CHECK-128-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Y]], align 8, !tbaa [[TBAA4]] -// CHECK-128-NEXT: store <16 x i8> [[TMP0]], ptr [[SAVED_VALUE]], align 16, !tbaa [[TBAA4]] -// CHECK-128-NEXT: [[TMP1:%.*]] = load , ptr [[SAVED_VALUE]], align 16, !tbaa [[TBAA4]] +// CHECK-128-NEXT: [[CAST_SCALABLE:%.*]] = tail call @llvm.vector.insert.nxv8i8.v16i8( undef, <16 x i8> [[TMP0]], i64 0) +// CHECK-128-NEXT: [[TMP1:%.*]] = bitcast [[CAST_SCALABLE]] to // CHECK-128-NEXT: ret [[TMP1]] // // CHECK-256-LABEL: @read_bool1( // CHECK-256-NEXT: entry: -// CHECK-256-NEXT: [[SAVED_VALUE:%.*]] = alloca <32 x i8>, align 32 // CHECK-256-NEXT: [[Y:%.*]] = getelementptr inbounds i8, ptr [[S:%.*]], i64 32 // CHECK-256-NEXT: [[TMP0:%.*]] = load <32 x i8>, ptr [[Y]], align 8, !tbaa [[TBAA4]] -// CHECK-256-NEXT: store <32 x i8> [[TMP0]], ptr [[SAVED_VALUE]], align 32, !tbaa [[TBAA4]] -// CHECK-256-NEXT: [[TMP1:%.*]] = load , ptr [[SAVED_VALUE]], align 32, !tbaa [[TBAA4]] +// CHECK-256-NEXT: [[CAST_SCALABLE:%.*]] = tail call @llvm.vector.insert.nxv8i8.v32i8( undef, <32 x i8> [[TMP0]], i64 0) +// CHECK-256-NEXT: [[TMP1:%.*]] = bitcast [[CAST_SCALABLE]] to // CHECK-256-NEXT: ret [[TMP1]] // vbool1_t read_bool1(struct struct_bool1 *s) { @@ -208,29 +205,26 @@ vbool1_t read_bool1(struct struct_bool1 *s) { // CHECK-64-LABEL: @write_bool1( // CHECK-64-NEXT: entry: -// CHECK-64-NEXT: [[SAVED_VALUE:%.*]] = alloca , align 8 -// CHECK-64-NEXT: store [[X:%.*]], ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA7:![0-9]+]] -// CHECK-64-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA4]] +// CHECK-64-NEXT: [[TMP0:%.*]] = bitcast [[X:%.*]] to +// CHECK-64-NEXT: [[CAST_FIXED:%.*]] = tail call <8 x i8> @llvm.vector.extract.v8i8.nxv8i8( [[TMP0]], i64 0) // CHECK-64-NEXT: [[Y:%.*]] = getelementptr inbounds i8, ptr [[S:%.*]], i64 8 -// CHECK-64-NEXT: store <8 x i8> [[TMP0]], ptr [[Y]], align 8, !tbaa [[TBAA4]] +// CHECK-64-NEXT: store <8 x i8> [[CAST_FIXED]], ptr [[Y]], align 8, !tbaa [[TBAA4]] // CHECK-64-NEXT: ret void // // CHECK-128-LABEL: @write_bool1( // CHECK-128-NEXT: entry: -// CHECK-128-NEXT: [[SAVED_VALUE:%.*]] = alloca , align 16 -// CHECK-128-NEXT: store [[X:%.*]], ptr [[SAVED_VALUE]], align 16, !tbaa [[TBAA7:![0-9]+]] -// CHECK-128-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[SAVED_VALUE]], align 16, !tbaa [[TBAA4]] +// CHECK-128-NEXT: [[TMP0:%.*]] = bitcast [[X:%.*]] to +// CHECK-128-NEXT: [[CAST_FIXED:%.*]] = tail call <16 x i8> @llvm.vector.extract.v16i8.nxv8i8( [[TMP0]], i64 0) // CHECK-128-NEXT: [[Y:%.*]] = getelementptr inbounds i8, ptr [[S:%.*]], i64 16 -// CHECK-128-NEXT: store <16 x i8> [[TMP0]], ptr [[Y]], align 8, !tbaa [[TBAA4]] +// CHECK-128-NEXT: store <16 x i8> [[CAST_FIXED]], ptr [[Y]], align 8, !tbaa [[TBAA4]] // CHECK-128-NEXT: ret void // // CHECK-256-LABEL: @write_bool1( // CHECK-256-NEXT: entry: -// CHECK-256-NEXT: [[SAVED_VALUE:%.*]] = alloca , align 8 -// CHECK-256-NEXT: store [[X:%.*]], ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA7:![0-9]+]] -// CHECK-256-NEXT: [[TMP0:%.*]] = load <32 x i8>, ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA4]] +// CHECK-256-NEXT: [[TMP0:%.*]] = bitcast [[X:%.*]] to +// CHECK-256-NEXT: [[CAST_FIXED:%.*]] = tail call <32 x i8> @llvm.vector.extract.v32i8.nxv8i8( [[TMP0]], i64 0) // CHECK-256-NEXT: [[Y:%.*]] = getelementptr inbounds i8, ptr [[S:%.*]], i64 32 -// CHECK-256-NEXT: store <32 x i8> [[TMP0]], ptr [[Y]], align 8, !tbaa [[TBAA4]] +// CHECK-256-NEXT: store <32 x i8> [[CAST_FIXED]], ptr [[Y]], align 8, !tbaa [[TBAA4]] // CHECK-256-NEXT: ret void // void write_bool1(struct struct_bool1 *s, vbool1_t x) { diff --git a/clang/test/CodeGen/attr-riscv-rvv-vector-bits-call.c b/clang/test/CodeGen/attr-riscv-rvv-vector-bits-call.c index 888abe1a7bc3fb5cdfe3b8ddb0fb17a322d62265..1824d97d04dda8f6902aa6b8e36098dffe339e15 100644 --- a/clang/test/CodeGen/attr-riscv-rvv-vector-bits-call.c +++ b/clang/test/CodeGen/attr-riscv-rvv-vector-bits-call.c @@ -70,13 +70,7 @@ fixed_float64m1_t call_float64_ff(fixed_float64m1_t op1, fixed_float64m1_t op2) // CHECK-LABEL: @call_bool1_ff( // CHECK-NEXT: entry: -// CHECK-NEXT: [[SAVED_VALUE4:%.*]] = alloca , align 8 -// CHECK-NEXT: [[RETVAL_COERCE:%.*]] = alloca , align 8 -// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.riscv.vmand.nxv64i1.i64( [[OP1_COERCE:%.*]], [[OP2_COERCE:%.*]], i64 256) -// CHECK-NEXT: store [[TMP0]], ptr [[SAVED_VALUE4]], align 8, !tbaa [[TBAA4:![0-9]+]] -// CHECK-NEXT: [[TMP1:%.*]] = load <32 x i8>, ptr [[SAVED_VALUE4]], align 8, !tbaa [[TBAA8:![0-9]+]] -// CHECK-NEXT: store <32 x i8> [[TMP1]], ptr [[RETVAL_COERCE]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = load , ptr [[RETVAL_COERCE]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.riscv.vmand.nxv64i1.i64( [[TMP0:%.*]], [[TMP1:%.*]], i64 256) // CHECK-NEXT: ret [[TMP2]] // fixed_bool1_t call_bool1_ff(fixed_bool1_t op1, fixed_bool1_t op2) { @@ -116,14 +110,8 @@ fixed_float64m1_t call_float64_fs(fixed_float64m1_t op1, vfloat64m1_t op2) { // CHECK-LABEL: @call_bool1_fs( // CHECK-NEXT: entry: -// CHECK-NEXT: [[SAVED_VALUE2:%.*]] = alloca , align 8 -// CHECK-NEXT: [[RETVAL_COERCE:%.*]] = alloca , align 8 -// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.riscv.vmand.nxv64i1.i64( [[OP1_COERCE:%.*]], [[OP2:%.*]], i64 256) -// CHECK-NEXT: store [[TMP0]], ptr [[SAVED_VALUE2]], align 8, !tbaa [[TBAA4]] -// CHECK-NEXT: [[TMP1:%.*]] = load <32 x i8>, ptr [[SAVED_VALUE2]], align 8, !tbaa [[TBAA8]] -// CHECK-NEXT: store <32 x i8> [[TMP1]], ptr [[RETVAL_COERCE]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = load , ptr [[RETVAL_COERCE]], align 8 -// CHECK-NEXT: ret [[TMP2]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.riscv.vmand.nxv64i1.i64( [[TMP0:%.*]], [[OP2:%.*]], i64 256) +// CHECK-NEXT: ret [[TMP1]] // fixed_bool1_t call_bool1_fs(fixed_bool1_t op1, vbool1_t op2) { return __riscv_vmand(op1, op2, __riscv_v_fixed_vlen); @@ -162,14 +150,8 @@ fixed_float64m1_t call_float64_ss(vfloat64m1_t op1, vfloat64m1_t op2) { // CHECK-LABEL: @call_bool1_ss( // CHECK-NEXT: entry: -// CHECK-NEXT: [[SAVED_VALUE:%.*]] = alloca , align 8 -// CHECK-NEXT: [[RETVAL_COERCE:%.*]] = alloca , align 8 // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.riscv.vmand.nxv64i1.i64( [[OP1:%.*]], [[OP2:%.*]], i64 256) -// CHECK-NEXT: store [[TMP0]], ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA4]] -// CHECK-NEXT: [[TMP1:%.*]] = load <32 x i8>, ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA8]] -// CHECK-NEXT: store <32 x i8> [[TMP1]], ptr [[RETVAL_COERCE]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = load , ptr [[RETVAL_COERCE]], align 8 -// CHECK-NEXT: ret [[TMP2]] +// CHECK-NEXT: ret [[TMP0]] // fixed_bool1_t call_bool1_ss(vbool1_t op1, vbool1_t op2) { return __riscv_vmand(op1, op2, __riscv_v_fixed_vlen); diff --git a/clang/test/CodeGen/attr-riscv-rvv-vector-bits-cast.c b/clang/test/CodeGen/attr-riscv-rvv-vector-bits-cast.c index fe278174bf6817c7e1fe01e3e7f7be8071ff04c1..3806c3e1b30bbfeea846aa4ac62cf3b670223b04 100644 --- a/clang/test/CodeGen/attr-riscv-rvv-vector-bits-cast.c +++ b/clang/test/CodeGen/attr-riscv-rvv-vector-bits-cast.c @@ -65,13 +65,7 @@ fixed_float64m1_t from_vfloat64m1_t(vfloat64m1_t type) { // CHECK-LABEL: @from_vbool1_t( // CHECK-NEXT: entry: -// CHECK-NEXT: [[SAVED_VALUE:%.*]] = alloca , align 8 -// CHECK-NEXT: [[RETVAL_COERCE:%.*]] = alloca , align 8 -// CHECK-NEXT: store [[TYPE:%.*]], ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA4:![0-9]+]] -// CHECK-NEXT: [[TMP0:%.*]] = load <32 x i8>, ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA8:![0-9]+]] -// CHECK-NEXT: store <32 x i8> [[TMP0]], ptr [[RETVAL_COERCE]], align 8 -// CHECK-NEXT: [[TMP1:%.*]] = load , ptr [[RETVAL_COERCE]], align 8 -// CHECK-NEXT: ret [[TMP1]] +// CHECK-NEXT: ret [[TYPE:%.*]] // fixed_bool1_t from_vbool1_t(vbool1_t type) { return type; @@ -79,7 +73,7 @@ fixed_bool1_t from_vbool1_t(vbool1_t type) { // CHECK-LABEL: @to_vbool1_t( // CHECK-NEXT: entry: -// CHECK-NEXT: ret [[TYPE_COERCE:%.*]] +// CHECK-NEXT: ret [[TMP0:%.*]] // vbool1_t to_vbool1_t(fixed_bool1_t type) { return type; @@ -105,8 +99,8 @@ vbool4_t to_vbool4_t(fixed_bool4_t type) { // CHECK-NEXT: entry: // CHECK-NEXT: [[SAVED_VALUE:%.*]] = alloca , align 1 // CHECK-NEXT: [[RETVAL_COERCE:%.*]] = alloca , align 1 -// CHECK-NEXT: store [[TYPE:%.*]], ptr [[SAVED_VALUE]], align 1, !tbaa [[TBAA9:![0-9]+]] -// CHECK-NEXT: [[TMP0:%.*]] = load <1 x i8>, ptr [[SAVED_VALUE]], align 1, !tbaa [[TBAA8]] +// CHECK-NEXT: store [[TYPE:%.*]], ptr [[SAVED_VALUE]], align 1, !tbaa [[TBAA4:![0-9]+]] +// CHECK-NEXT: [[TMP0:%.*]] = load <1 x i8>, ptr [[SAVED_VALUE]], align 1, !tbaa [[TBAA8:![0-9]+]] // CHECK-NEXT: store <1 x i8> [[TMP0]], ptr [[RETVAL_COERCE]], align 1 // CHECK-NEXT: [[TMP1:%.*]] = load , ptr [[RETVAL_COERCE]], align 1 // CHECK-NEXT: ret [[TMP1]] diff --git a/clang/test/CodeGen/attr-riscv-rvv-vector-bits-codegen.c b/clang/test/CodeGen/attr-riscv-rvv-vector-bits-codegen.c index ac22bdce0da3e5fe37dc91ae5886ff429e84bf83..eb769fadda9a858d553858dcdddf394867972b78 100644 --- a/clang/test/CodeGen/attr-riscv-rvv-vector-bits-codegen.c +++ b/clang/test/CodeGen/attr-riscv-rvv-vector-bits-codegen.c @@ -53,25 +53,24 @@ fixed_bool32_t global_bool32; // CHECK-NEXT: [[M_ADDR:%.*]] = alloca , align 1 // CHECK-NEXT: [[VEC_ADDR:%.*]] = alloca , align 1 // CHECK-NEXT: [[MASK:%.*]] = alloca , align 1 -// CHECK-NEXT: [[SAVED_VALUE:%.*]] = alloca <32 x i8>, align 32 // CHECK-NEXT: store [[M:%.*]], ptr [[M_ADDR]], align 1 // CHECK-NEXT: store [[VEC:%.*]], ptr [[VEC_ADDR]], align 1 // CHECK-NEXT: [[TMP0:%.*]] = load , ptr [[M_ADDR]], align 1 // CHECK-NEXT: [[TMP1:%.*]] = load <32 x i8>, ptr @global_bool1, align 8 -// CHECK-NEXT: store <32 x i8> [[TMP1]], ptr [[SAVED_VALUE]], align 32 -// CHECK-NEXT: [[TMP2:%.*]] = load , ptr [[SAVED_VALUE]], align 32 +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv8i8.v32i8( undef, <32 x i8> [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CAST_SCALABLE]] to // CHECK-NEXT: [[TMP3:%.*]] = call @llvm.riscv.vmand.nxv64i1.i64( [[TMP0]], [[TMP2]], i64 256) // CHECK-NEXT: store [[TMP3]], ptr [[MASK]], align 1 // CHECK-NEXT: [[TMP4:%.*]] = load , ptr [[MASK]], align 1 // CHECK-NEXT: [[TMP5:%.*]] = load , ptr [[VEC_ADDR]], align 1 // CHECK-NEXT: [[TMP6:%.*]] = load <256 x i8>, ptr @global_vec_int8m8, align 8 -// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv64i8.v256i8( undef, <256 x i8> [[TMP6]], i64 0) -// CHECK-NEXT: [[TMP7:%.*]] = call @llvm.riscv.vadd.mask.nxv64i8.nxv64i8.i64( poison, [[TMP5]], [[CAST_SCALABLE]], [[TMP4]], i64 256, i64 3) +// CHECK-NEXT: [[CAST_SCALABLE1:%.*]] = call @llvm.vector.insert.nxv64i8.v256i8( undef, <256 x i8> [[TMP6]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = call @llvm.riscv.vadd.mask.nxv64i8.nxv64i8.i64( poison, [[TMP5]], [[CAST_SCALABLE1]], [[TMP4]], i64 256, i64 3) // CHECK-NEXT: [[CAST_FIXED:%.*]] = call <256 x i8> @llvm.vector.extract.v256i8.nxv64i8( [[TMP7]], i64 0) // CHECK-NEXT: store <256 x i8> [[CAST_FIXED]], ptr [[RETVAL]], align 8 // CHECK-NEXT: [[TMP8:%.*]] = load <256 x i8>, ptr [[RETVAL]], align 8 -// CHECK-NEXT: [[CAST_SCALABLE1:%.*]] = call @llvm.vector.insert.nxv64i8.v256i8( undef, <256 x i8> [[TMP8]], i64 0) -// CHECK-NEXT: ret [[CAST_SCALABLE1]] +// CHECK-NEXT: [[CAST_SCALABLE2:%.*]] = call @llvm.vector.insert.nxv64i8.v256i8( undef, <256 x i8> [[TMP8]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE2]] // fixed_int8m8_t test_bool1(vbool1_t m, vint8m8_t vec) { vbool1_t mask = __riscv_vmand(m, global_bool1, __riscv_v_fixed_vlen); @@ -181,15 +180,15 @@ fixed_int32m1_t array_arg(fixed_int32m1_t arr[]) { // CHECK-NEXT: [[RETVAL:%.*]] = alloca <32 x i8>, align 8 // CHECK-NEXT: [[ARR:%.*]] = alloca [3 x <32 x i8>], align 8 // CHECK-NEXT: [[PARR:%.*]] = alloca ptr, align 8 -// CHECK-NEXT: [[RETVAL_COERCE:%.*]] = alloca , align 8 // CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <32 x i8>], ptr [[ARR]], i64 0, i64 0 // CHECK-NEXT: store ptr [[ARRAYIDX]], ptr [[PARR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[PARR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load <32 x i8>, ptr [[TMP0]], align 8 // CHECK-NEXT: store <32 x i8> [[TMP1]], ptr [[RETVAL]], align 8 -// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL_COERCE]], ptr align 8 [[RETVAL]], i64 32, i1 false) -// CHECK-NEXT: [[TMP2:%.*]] = load , ptr [[RETVAL_COERCE]], align 8 -// CHECK-NEXT: ret [[TMP2]] +// CHECK-NEXT: [[TMP2:%.*]] = load <32 x i8>, ptr [[RETVAL]], align 8 +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv8i8.v32i8( undef, <32 x i8> [[TMP2]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = bitcast [[CAST_SCALABLE]] to +// CHECK-NEXT: ret [[TMP3]] // fixed_bool1_t address_of_array_idx_bool1() { fixed_bool1_t arr[3]; diff --git a/clang/test/CodeGen/attr-riscv-rvv-vector-bits-globals.c b/clang/test/CodeGen/attr-riscv-rvv-vector-bits-globals.c index d7df1a24bbfb003861a2451d76777544acc81b12..31a245dcb2240547f369315b13f15f3f3afe93dd 100644 --- a/clang/test/CodeGen/attr-riscv-rvv-vector-bits-globals.c +++ b/clang/test/CodeGen/attr-riscv-rvv-vector-bits-globals.c @@ -56,18 +56,16 @@ void write_global_i64(vint64m1_t v) { global_i64 = v; } // CHECK-64-LABEL: @write_global_bool1( // CHECK-64-NEXT: entry: -// CHECK-64-NEXT: [[SAVED_VALUE:%.*]] = alloca , align 8 -// CHECK-64-NEXT: store [[V:%.*]], ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA7:![0-9]+]] -// CHECK-64-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA4]] -// CHECK-64-NEXT: store <8 x i8> [[TMP0]], ptr @global_bool1, align 8, !tbaa [[TBAA4]] +// CHECK-64-NEXT: [[TMP0:%.*]] = bitcast [[V:%.*]] to +// CHECK-64-NEXT: [[CAST_FIXED:%.*]] = tail call <8 x i8> @llvm.vector.extract.v8i8.nxv8i8( [[TMP0]], i64 0) +// CHECK-64-NEXT: store <8 x i8> [[CAST_FIXED]], ptr @global_bool1, align 8, !tbaa [[TBAA4]] // CHECK-64-NEXT: ret void // // CHECK-256-LABEL: @write_global_bool1( // CHECK-256-NEXT: entry: -// CHECK-256-NEXT: [[SAVED_VALUE:%.*]] = alloca , align 8 -// CHECK-256-NEXT: store [[V:%.*]], ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA7:![0-9]+]] -// CHECK-256-NEXT: [[TMP0:%.*]] = load <32 x i8>, ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA4]] -// CHECK-256-NEXT: store <32 x i8> [[TMP0]], ptr @global_bool1, align 8, !tbaa [[TBAA4]] +// CHECK-256-NEXT: [[TMP0:%.*]] = bitcast [[V:%.*]] to +// CHECK-256-NEXT: [[CAST_FIXED:%.*]] = tail call <32 x i8> @llvm.vector.extract.v32i8.nxv8i8( [[TMP0]], i64 0) +// CHECK-256-NEXT: store <32 x i8> [[CAST_FIXED]], ptr @global_bool1, align 8, !tbaa [[TBAA4]] // CHECK-256-NEXT: ret void // void write_global_bool1(vbool1_t v) { global_bool1 = v; } @@ -92,7 +90,7 @@ void write_global_bool4(vbool4_t v) { global_bool4 = v; } // CHECK-256-LABEL: @write_global_bool32( // CHECK-256-NEXT: entry: // CHECK-256-NEXT: [[SAVED_VALUE:%.*]] = alloca , align 1 -// CHECK-256-NEXT: store [[V:%.*]], ptr [[SAVED_VALUE]], align 1, !tbaa [[TBAA9:![0-9]+]] +// CHECK-256-NEXT: store [[V:%.*]], ptr [[SAVED_VALUE]], align 1, !tbaa [[TBAA7:![0-9]+]] // CHECK-256-NEXT: [[TMP0:%.*]] = load <1 x i8>, ptr [[SAVED_VALUE]], align 1, !tbaa [[TBAA4]] // CHECK-256-NEXT: store <1 x i8> [[TMP0]], ptr @global_bool32, align 1, !tbaa [[TBAA4]] // CHECK-256-NEXT: ret void @@ -120,18 +118,16 @@ vint64m1_t read_global_i64() { return global_i64; } // CHECK-64-LABEL: @read_global_bool1( // CHECK-64-NEXT: entry: -// CHECK-64-NEXT: [[SAVED_VALUE:%.*]] = alloca <8 x i8>, align 8 // CHECK-64-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr @global_bool1, align 8, !tbaa [[TBAA4]] -// CHECK-64-NEXT: store <8 x i8> [[TMP0]], ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA4]] -// CHECK-64-NEXT: [[TMP1:%.*]] = load , ptr [[SAVED_VALUE]], align 8, !tbaa [[TBAA4]] +// CHECK-64-NEXT: [[CAST_SCALABLE:%.*]] = tail call @llvm.vector.insert.nxv8i8.v8i8( undef, <8 x i8> [[TMP0]], i64 0) +// CHECK-64-NEXT: [[TMP1:%.*]] = bitcast [[CAST_SCALABLE]] to // CHECK-64-NEXT: ret [[TMP1]] // // CHECK-256-LABEL: @read_global_bool1( // CHECK-256-NEXT: entry: -// CHECK-256-NEXT: [[SAVED_VALUE:%.*]] = alloca <32 x i8>, align 32 // CHECK-256-NEXT: [[TMP0:%.*]] = load <32 x i8>, ptr @global_bool1, align 8, !tbaa [[TBAA4]] -// CHECK-256-NEXT: store <32 x i8> [[TMP0]], ptr [[SAVED_VALUE]], align 32, !tbaa [[TBAA4]] -// CHECK-256-NEXT: [[TMP1:%.*]] = load , ptr [[SAVED_VALUE]], align 32, !tbaa [[TBAA4]] +// CHECK-256-NEXT: [[CAST_SCALABLE:%.*]] = tail call @llvm.vector.insert.nxv8i8.v32i8( undef, <32 x i8> [[TMP0]], i64 0) +// CHECK-256-NEXT: [[TMP1:%.*]] = bitcast [[CAST_SCALABLE]] to // CHECK-256-NEXT: ret [[TMP1]] // vbool1_t read_global_bool1() { return global_bool1; } diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c index 2a96697e4291b9b57108ac7f298601d75d7be7ec..c27d48f3ecf681dcdfbc237c57d0fbaf89d2d95a 100644 --- a/clang/test/CodeGen/attr-target-version.c +++ b/clang/test/CodeGen/attr-target-version.c @@ -90,13 +90,20 @@ int hoo(void) { //. // CHECK: @__aarch64_cpu_features = external dso_local global { i64 } -// CHECK: @fmv.ifunc = weak_odr ifunc i32 (), ptr @fmv.resolver -// CHECK: @fmv_one.ifunc = weak_odr ifunc i32 (), ptr @fmv_one.resolver -// CHECK: @fmv_two.ifunc = weak_odr ifunc i32 (), ptr @fmv_two.resolver -// CHECK: @fmv_e.ifunc = weak_odr ifunc i32 (), ptr @fmv_e.resolver -// CHECK: @fmv_c.ifunc = weak_odr ifunc void (), ptr @fmv_c.resolver -// CHECK: @fmv_inline.ifunc = weak_odr ifunc i32 (), ptr @fmv_inline.resolver -// CHECK: @fmv_d.ifunc = internal ifunc i32 (), ptr @fmv_d.resolver +// CHECK: @fmv.ifunc = weak_odr alias i32 (), ptr @fmv +// CHECK: @fmv_one.ifunc = weak_odr alias i32 (), ptr @fmv_one +// CHECK: @fmv_two.ifunc = weak_odr alias i32 (), ptr @fmv_two +// CHECK: @fmv_e.ifunc = weak_odr alias i32 (), ptr @fmv_e +// CHECK: @fmv_inline.ifunc = weak_odr alias i32 (), ptr @fmv_inline +// CHECK: @fmv_d.ifunc = internal alias i32 (), ptr @fmv_d +// CHECK: @fmv_c.ifunc = weak_odr alias void (), ptr @fmv_c +// CHECK: @fmv = weak_odr ifunc i32 (), ptr @fmv.resolver +// CHECK: @fmv_one = weak_odr ifunc i32 (), ptr @fmv_one.resolver +// CHECK: @fmv_two = weak_odr ifunc i32 (), ptr @fmv_two.resolver +// CHECK: @fmv_e = weak_odr ifunc i32 (), ptr @fmv_e.resolver +// CHECK: @fmv_inline = weak_odr ifunc i32 (), ptr @fmv_inline.resolver +// CHECK: @fmv_d = internal ifunc i32 (), ptr @fmv_d.resolver +// CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver //. // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv._MrngMflagmMfp16fml @@ -105,6 +112,32 @@ int hoo(void) { // CHECK-NEXT: ret i32 1 // // +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_one._MsimdMls64 +// CHECK-SAME: () #[[ATTR1:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_two._Mfp +// CHECK-SAME: () #[[ATTR1]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@foo +// CHECK-SAME: () #[[ATTR2:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv() +// CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_one() +// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]] +// CHECK-NEXT: [[CALL2:%.*]] = call i32 @fmv_two() +// CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]] +// CHECK-NEXT: ret i32 [[ADD3]] +// +// // CHECK-LABEL: define {{[^@]+}}@fmv.resolver() comdat { // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -183,42 +216,16 @@ int hoo(void) { // CHECK-NEXT: ret ptr @fmv.default // // -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_one._MsimdMls64 -// CHECK-SAME: () #[[ATTR1:[0-9]+]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 -// -// // CHECK-LABEL: define {{[^@]+}}@fmv_one.resolver() comdat { // CHECK-NEXT: resolver_entry: // CHECK-NEXT: ret ptr @fmv_one._MsimdMls64 // // -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_two._Mfp -// CHECK-SAME: () #[[ATTR1]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 -// -// // CHECK-LABEL: define {{[^@]+}}@fmv_two.resolver() comdat { // CHECK-NEXT: resolver_entry: // CHECK-NEXT: ret ptr @fmv_two._MsimdMfp16 // // -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@foo -// CHECK-SAME: () #[[ATTR2:[0-9]+]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv.ifunc() -// CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_one.ifunc() -// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]] -// CHECK-NEXT: [[CALL2:%.*]] = call i32 @fmv_two.ifunc() -// CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]] -// CHECK-NEXT: ret i32 [[ADD3]] -// -// // CHECK-LABEL: define {{[^@]+}}@fmv_e.resolver() comdat { // CHECK-NEXT: resolver_entry: // CHECK-NEXT: ret ptr @fmv_e._Mls64 @@ -238,28 +245,14 @@ int hoo(void) { // CHECK-NEXT: ret void // // -// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat { -// CHECK-NEXT: resolver_entry: -// CHECK-NEXT: call void @__init_cpu_features_resolver() -// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 281474976710656 -// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656 -// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] -// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] -// CHECK: resolver_return: -// CHECK-NEXT: ret ptr @fmv_c._Mssbs -// CHECK: resolver_else: -// CHECK-NEXT: ret ptr @fmv_c.default -// -// // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@goo // CHECK-SAME: () #[[ATTR2]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv_inline.ifunc() -// CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_e.ifunc() -// CHECK-NEXT: [[CALL2:%.*]] = call i32 @fmv_d.ifunc() -// CHECK-NEXT: call void @fmv_c.ifunc() +// CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv_inline() +// CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_e() +// CHECK-NEXT: [[CALL2:%.*]] = call i32 @fmv_d() +// CHECK-NEXT: call void @fmv_c() // CHECK-NEXT: [[CALL3:%.*]] = call i32 @fmv_default() // CHECK-NEXT: ret i32 [[CALL3]] // @@ -412,6 +405,20 @@ int hoo(void) { // CHECK-NEXT: ret ptr @fmv_d.default // // +// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 281474976710656 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @fmv_c._Mssbs +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @fmv_c.default +// +// // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@recur // CHECK-SAME: () #[[ATTR2]] { @@ -437,9 +444,9 @@ int hoo(void) { // CHECK-NEXT: entry: // CHECK-NEXT: [[FP1:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[FP2:%.*]] = alloca ptr, align 8 -// CHECK-NEXT: call void @f(ptr noundef @fmv.ifunc) -// CHECK-NEXT: store ptr @fmv.ifunc, ptr [[FP1]], align 8 -// CHECK-NEXT: store ptr @fmv.ifunc, ptr [[FP2]], align 8 +// CHECK-NEXT: call void @f(ptr noundef @fmv) +// CHECK-NEXT: store ptr @fmv, ptr [[FP1]], align 8 +// CHECK-NEXT: store ptr @fmv, ptr [[FP2]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[FP1]], align 8 // CHECK-NEXT: [[CALL:%.*]] = call i32 [[TMP0]]() // CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[FP2]], align 8 @@ -561,13 +568,6 @@ int hoo(void) { // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_c.default -// CHECK-SAME: () #[[ATTR2]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret void -// -// -// CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msha1MpmullMf64mm // CHECK-SAME: () #[[ATTR12:[0-9]+]] { // CHECK-NEXT: entry: @@ -700,6 +700,13 @@ int hoo(void) { // CHECK-NEXT: ret i32 1 // // +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_c.default +// CHECK-SAME: () #[[ATTR2]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +// // CHECK-NOFMV: Function Attrs: noinline nounwind optnone // CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv // CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] { diff --git a/clang/test/CodeGen/builtins-nvptx.c b/clang/test/CodeGen/builtins-nvptx.c index ad7c27f2d60d26a023a8d70fb268b02901091495..4dba7670b5c43ef5d1a3e70f17d3c826e28bd40d 100644 --- a/clang/test/CodeGen/builtins-nvptx.c +++ b/clang/test/CodeGen/builtins-nvptx.c @@ -44,6 +44,14 @@ __device__ int read_tid() { } +__device__ bool reflect() { + +// CHECK: call i32 @llvm.nvvm.reflect(ptr {{.*}}) + + unsigned x = __nvvm_reflect("__CUDA_ARCH"); + return x >= 700; +} + __device__ int read_ntid() { // CHECK: call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c index ed03233b6f1a967c845306de8ff27855bfc6fd99..88282120283b8a6f697c28a52747a8728b312b51 100644 --- a/clang/test/CodeGen/builtins.c +++ b/clang/test/CodeGen/builtins.c @@ -496,6 +496,12 @@ long long test_builtin_readcyclecounter(void) { return __builtin_readcyclecounter(); } +// CHECK-LABEL: define{{.*}} i64 @test_builtin_readsteadycounter +long long test_builtin_readsteadycounter(void) { + // CHECK: call i64 @llvm.readsteadycounter() + return __builtin_readsteadycounter(); +} + /// __builtin_launder should be a NOP in C since there are no vtables. // CHECK-LABEL: define{{.*}} void @test_builtin_launder void test_builtin_launder(int *p) { diff --git a/clang/test/CodeGen/c11atomics.c b/clang/test/CodeGen/c11atomics.c index dd1f52f70ae09fd2c39a974390ab3e331363793d..4da36ad4da0f92fd32a05d56db2f8288b3c7c740 100644 --- a/clang/test/CodeGen/c11atomics.c +++ b/clang/test/CodeGen/c11atomics.c @@ -343,10 +343,9 @@ PS test_promoted_load(_Atomic(PS) *addr) { // CHECK: [[ATOMIC_RES:%.*]] = alloca { %struct.PS, [2 x i8] }, align 8 // CHECK: store ptr %addr, ptr [[ADDR_ARG]], align 4 // CHECK: [[ADDR:%.*]] = load ptr, ptr [[ADDR_ARG]], align 4 - // CHECK: [[RES:%.*]] = call arm_aapcscc i64 @__atomic_load_8(ptr noundef [[ADDR]], i32 noundef 5) - // CHECK: store i64 [[RES]], ptr [[ATOMIC_RES]], align 8 - // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 2 %agg.result, ptr align 8 [[ATOMIC_RES]], i32 6, i1 false) - + // CHECK: [[ATOMIC_RES:%.*]] = load atomic i64, ptr [[ADDR]] seq_cst, align 8 + // CHECK: store i64 [[ATOMIC_RES]], ptr [[ATOMIC_RES_ADDR:%.*]], align 8 + // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 2 %agg.result, ptr align 8 [[ATOMIC_RES_ADDR]], i32 6, i1 false) return __c11_atomic_load(addr, 5); } @@ -362,8 +361,8 @@ void test_promoted_store(_Atomic(PS) *addr, PS *val) { // CHECK: [[VAL:%.*]] = load ptr, ptr [[VAL_ARG]], align 4 // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 2 [[NONATOMIC_TMP]], ptr align 2 [[VAL]], i32 6, i1 false) // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[ATOMIC_VAL]], ptr align 2 [[NONATOMIC_TMP]], i64 6, i1 false) - // CHECK: [[VAL64:%.*]] = load i64, ptr [[ATOMIC_VAL]], align 2 - // CHECK: call arm_aapcscc void @__atomic_store_8(ptr noundef [[ADDR]], i64 noundef [[VAL64]], i32 noundef 5) + // CHECK: [[ATOMIC:%.*]] = load i64, ptr [[ATOMIC_VAL]], align 8 + // CHECK: store atomic i64 [[ATOMIC]], ptr [[ADDR]] seq_cst, align 8 __c11_atomic_store(addr, *val, 5); } @@ -380,10 +379,10 @@ PS test_promoted_exchange(_Atomic(PS) *addr, PS *val) { // CHECK: [[VAL:%.*]] = load ptr, ptr [[VAL_ARG]], align 4 // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 2 [[NONATOMIC_TMP]], ptr align 2 [[VAL]], i32 6, i1 false) // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[ATOMIC_VAL]], ptr align 2 [[NONATOMIC_TMP]], i64 6, i1 false) - // CHECK: [[VAL64:%.*]] = load i64, ptr [[ATOMIC_VAL]], align 2 - // CHECK: [[RES:%.*]] = call arm_aapcscc i64 @__atomic_exchange_8(ptr noundef [[ADDR]], i64 noundef [[VAL64]], i32 noundef 5) - // CHECK: store i64 [[RES]], ptr [[ATOMIC_RES]], align 8 - // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 2 %agg.result, ptr align 8 [[ATOMIC_RES]], i32 6, i1 false) + // CHECK: [[ATOMIC:%.*]] = load i64, ptr [[ATOMIC_VAL]], align 8 + // CHECK: [[ATOMIC_RES:%.*]] = atomicrmw xchg ptr [[ADDR]], i64 [[ATOMIC]] seq_cst, align 8 + // CHECK: store i64 [[ATOMIC_RES]], ptr [[ATOMIC_RES_PTR:%.*]], align 8 + // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 2 %agg.result, ptr align 8 [[ATOMIC_RES_PTR]], i32 6, i1 false) return __c11_atomic_exchange(addr, *val, 5); } @@ -404,9 +403,10 @@ _Bool test_promoted_cmpxchg(_Atomic(PS) *addr, PS *desired, PS *new) { // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 2 [[NONATOMIC_TMP]], ptr align 2 [[NEW]], i32 6, i1 false) // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[ATOMIC_DESIRED]], ptr align 2 [[DESIRED]], i64 6, i1 false) // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[ATOMIC_NEW]], ptr align 2 [[NONATOMIC_TMP]], i64 6, i1 false) - // CHECK: [[NEW64:%.*]] = load i64, ptr [[ATOMIC_NEW]], align 2 - // CHECK: [[RES:%.*]] = call arm_aapcscc zeroext i1 @__atomic_compare_exchange_8(ptr noundef [[ADDR]], ptr noundef [[ATOMIC_DESIRED]], i64 noundef [[NEW64]], i32 noundef 5, i32 noundef 5) - // CHECK: ret i1 [[RES]] + // CHECK: [[VAL1:%.*]] = load i64, ptr [[ATOMIC_DESIRED]], align 8 + // CHECK: [[VAL2:%.*]] = load i64, ptr [[ATOMIC_NEW]], align 8 + // CHECK: [[RES_PAIR:%.*]] = cmpxchg ptr [[ADDR]], i64 [[VAL1]], i64 [[VAL2]] seq_cst seq_cst, align 8 + // CHECK: [[RES:%.*]] = extractvalue { i64, i1 } [[RES_PAIR]], 1 return __c11_atomic_compare_exchange_strong(addr, desired, *new, 5, 5); } @@ -414,12 +414,12 @@ struct Empty {}; struct Empty test_empty_struct_load(_Atomic(struct Empty)* empty) { // CHECK-LABEL: @test_empty_struct_load( - // CHECK: call arm_aapcscc zeroext i8 @__atomic_load_1(ptr noundef %{{.*}}, i32 noundef 5) + // CHECK: load atomic i8, ptr {{.*}}, align 1 return __c11_atomic_load(empty, 5); } void test_empty_struct_store(_Atomic(struct Empty)* empty, struct Empty value) { // CHECK-LABEL: @test_empty_struct_store( - // CHECK: call arm_aapcscc void @__atomic_store_1(ptr noundef %{{.*}}, i8 noundef zeroext %{{.*}}, i32 noundef 5) + // CHECK: store atomic i8 {{.*}}, ptr {{.*}}, align 1 __c11_atomic_store(empty, value, 5); } diff --git a/clang/test/CodeGen/fp128_complex.c b/clang/test/CodeGen/fp128_complex.c index 0e87cbe8ce812191326a8bbe4610a65492778b6d..d1593fae9c9bc291faaa24e683c38cd48375ce05 100644 --- a/clang/test/CodeGen/fp128_complex.c +++ b/clang/test/CodeGen/fp128_complex.c @@ -1,4 +1,4 @@ -// RUN: %clang -target aarch64-linux-gnueabi %s -S -emit-llvm -o - | FileCheck %s +// RUN: %clang --target=aarch64 %s -S -emit-llvm -o - | FileCheck %s _Complex long double a, b, c, d; void test_fp128_compound_assign(void) { diff --git a/clang/test/CodeGen/fp16-ops-strictfp.c b/clang/test/CodeGen/fp16-ops-strictfp.c index aa096fc796956c6a6ee9dba8a78bd0bd09b5bb1a..25753e5b98bebd97f0950f64bf93e972f03f4d96 100644 --- a/clang/test/CodeGen/fp16-ops-strictfp.c +++ b/clang/test/CodeGen/fp16-ops-strictfp.c @@ -1,10 +1,10 @@ // REQUIRES: arm-registered-target // RUN: %clang_cc1 -ffp-exception-behavior=maytrap -fexperimental-strict-floating-point -emit-llvm -o - -triple arm-none-linux-gnueabi %s | FileCheck %s --check-prefix=NOTNATIVE --check-prefix=CHECK -vv -dump-input=fail -// RUN: %clang_cc1 -ffp-exception-behavior=maytrap -emit-llvm -o - -triple aarch64-none-linux-gnueabi %s | FileCheck %s --check-prefix=NOTNATIVE --check-prefix=CHECK +// RUN: %clang_cc1 -ffp-exception-behavior=maytrap -emit-llvm -o - -triple aarch64 %s | FileCheck %s --check-prefix=NOTNATIVE --check-prefix=CHECK // RUN: %clang_cc1 -ffp-exception-behavior=maytrap -fexperimental-strict-floating-point -emit-llvm -o - -triple x86_64-linux-gnu %s | FileCheck %s --check-prefix=NOTNATIVE --check-prefix=CHECK // RUN: %clang_cc1 -ffp-exception-behavior=maytrap -fexperimental-strict-floating-point -emit-llvm -o - -triple arm-none-linux-gnueabi -fnative-half-type %s \ // RUN: | FileCheck %s --check-prefix=NATIVE-HALF --check-prefix=CHECK -// RUN: %clang_cc1 -ffp-exception-behavior=maytrap -emit-llvm -o - -triple aarch64-none-linux-gnueabi -fnative-half-type %s \ +// RUN: %clang_cc1 -ffp-exception-behavior=maytrap -emit-llvm -o - -triple aarch64 -fnative-half-type %s \ // RUN: | FileCheck %s --check-prefix=NATIVE-HALF --check-prefix=CHECK // // Test that the constrained intrinsics are picking up the exception diff --git a/clang/test/CodeGen/fp16-ops.c b/clang/test/CodeGen/fp16-ops.c index 0626e0aaed9d0c023aacb6341862a5239033321b..bfa2a2f7f6c8267a6049ede3979d4ce72f3d4787 100644 --- a/clang/test/CodeGen/fp16-ops.c +++ b/clang/test/CodeGen/fp16-ops.c @@ -1,10 +1,10 @@ // REQUIRES: arm-registered-target // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi %s | FileCheck %s --check-prefix=NOTNATIVE --check-prefix=CHECK -// RUN: %clang_cc1 -emit-llvm -o - -triple aarch64-none-linux-gnueabi %s | FileCheck %s --check-prefix=NOTNATIVE --check-prefix=CHECK +// RUN: %clang_cc1 -emit-llvm -o - -triple aarch64 %s | FileCheck %s --check-prefix=NOTNATIVE --check-prefix=CHECK // RUN: %clang_cc1 -emit-llvm -o - -triple x86_64-linux-gnu %s | FileCheck %s --check-prefix=NOTNATIVE --check-prefix=CHECK // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi -fnative-half-type %s \ // RUN: | FileCheck %s --check-prefix=NATIVE-HALF -// RUN: %clang_cc1 -emit-llvm -o - -triple aarch64-none-linux-gnueabi -fnative-half-type %s \ +// RUN: %clang_cc1 -emit-llvm -o - -triple aarch64 -fnative-half-type %s \ // RUN: | FileCheck %s --check-prefix=NATIVE-HALF // RUN: %clang_cc1 -emit-llvm -o - -x renderscript %s \ // RUN: | FileCheck %s --check-prefix=NATIVE-HALF diff --git a/clang/test/CodeGenCXX/atomic-inline.cpp b/clang/test/CodeGenCXX/atomic-inline.cpp index 701bbd57b485c72f0141ce23109499363043b9c6..c8fa877a37beb5d6771f573957d0043758ab3b89 100644 --- a/clang/test/CodeGenCXX/atomic-inline.cpp +++ b/clang/test/CodeGenCXX/atomic-inline.cpp @@ -42,7 +42,7 @@ AM16 m16; AM16 load16() { AM16 am; // CHECK-LABEL: @_Z6load16v - // CHECK: call void @__atomic_load + // CHECK: load atomic i128, {{.*}} monotonic, align 16 // CORE2-LABEL: @_Z6load16v // CORE2: load atomic i128, {{.*}} monotonic, align 16 __atomic_load(&m16, &am, 0); @@ -52,7 +52,7 @@ AM16 load16() { AM16 s16; void store16() { // CHECK-LABEL: @_Z7store16v - // CHECK: call void @__atomic_store + // CHECK: store atomic i128 {{.*}} monotonic, align 16 // CORE2-LABEL: @_Z7store16v // CORE2: store atomic i128 {{.*}} monotonic, align 16 __atomic_store(&m16, &s16, 0); @@ -61,7 +61,7 @@ void store16() { bool cmpxchg16() { AM16 am; // CHECK-LABEL: @_Z9cmpxchg16v - // CHECK: call noundef zeroext i1 @__atomic_compare_exchange + // CHECK: cmpxchg ptr {{.*}} monotonic monotonic, align 16 // CORE2-LABEL: @_Z9cmpxchg16v // CORE2: cmpxchg ptr {{.*}} monotonic monotonic, align 16 return __atomic_compare_exchange(&m16, &s16, &am, 0, 0, 0); diff --git a/clang/test/CodeGenCXX/attr-target-version.cpp b/clang/test/CodeGenCXX/attr-target-version.cpp index 68dd7be1180b48c6f80af6eff0db40ab58fd4e14..b63815db7e40fa760c92096b92902343cefaeada 100644 --- a/clang/test/CodeGenCXX/attr-target-version.cpp +++ b/clang/test/CodeGenCXX/attr-target-version.cpp @@ -26,9 +26,12 @@ int bar() { //. // CHECK: @__aarch64_cpu_features = external dso_local global { i64 } -// CHECK: @_Z3fooi.ifunc = weak_odr ifunc i32 (i32), ptr @_Z3fooi.resolver -// CHECK: @_Z3foov.ifunc = weak_odr ifunc i32 (), ptr @_Z3foov.resolver -// CHECK: @_ZN7MyClass3gooEi.ifunc = weak_odr ifunc i32 (ptr, i32), ptr @_ZN7MyClass3gooEi.resolver +// CHECK: @_ZN7MyClass3gooEi.ifunc = weak_odr alias i32 (ptr, i32), ptr @_ZN7MyClass3gooEi +// CHECK: @_Z3fooi.ifunc = weak_odr alias i32 (i32), ptr @_Z3fooi +// CHECK: @_Z3foov.ifunc = weak_odr alias i32 (), ptr @_Z3foov +// CHECK: @_ZN7MyClass3gooEi = weak_odr ifunc i32 (ptr, i32), ptr @_ZN7MyClass3gooEi.resolver +// CHECK: @_Z3fooi = weak_odr ifunc i32 (i32), ptr @_Z3fooi.resolver +// CHECK: @_Z3foov = weak_odr ifunc i32 (), ptr @_Z3foov.resolver //. // CHECK-LABEL: @_Z3fooi._Mbf16Msme-f64f64( // CHECK-NEXT: entry: @@ -37,39 +40,11 @@ int bar() { // CHECK-NEXT: ret i32 1 // // -// CHECK-LABEL: @_Z3fooi.resolver( -// CHECK-NEXT: resolver_entry: -// CHECK-NEXT: call void @__init_cpu_features_resolver() -// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 36028797153181696 -// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 36028797153181696 -// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] -// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] -// CHECK: resolver_return: -// CHECK-NEXT: ret ptr @_Z3fooi._Mbf16Msme-f64f64 -// CHECK: resolver_else: -// CHECK-NEXT: ret ptr @_Z3fooi.default -// -// // CHECK-LABEL: @_Z3foov._Msm4Mebf16( // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 3 // // -// CHECK-LABEL: @_Z3foov.resolver( -// CHECK-NEXT: resolver_entry: -// CHECK-NEXT: call void @__init_cpu_features_resolver() -// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 268435488 -// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 268435488 -// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] -// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] -// CHECK: resolver_return: -// CHECK-NEXT: ret ptr @_Z3foov._Msm4Mebf16 -// CHECK: resolver_else: -// CHECK-NEXT: ret ptr @_Z3foov.default -// -// // CHECK-LABEL: @_ZN7MyClass3gooEi.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -95,24 +70,40 @@ int bar() { // CHECK-LABEL: @_Z3barv( // CHECK-NEXT: entry: // CHECK-NEXT: [[M:%.*]] = alloca [[STRUCT_MYCLASS:%.*]], align 1 -// CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZN7MyClass3gooEi.ifunc(ptr noundef nonnull align 1 dereferenceable(1) [[M]], i32 noundef 1) -// CHECK-NEXT: [[CALL1:%.*]] = call noundef i32 @_Z3fooi.ifunc(i32 noundef 1) +// CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZN7MyClass3gooEi(ptr noundef nonnull align 1 dereferenceable(1) [[M]], i32 noundef 1) +// CHECK-NEXT: [[CALL1:%.*]] = call noundef i32 @_Z3fooi(i32 noundef 1) // CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]] -// CHECK-NEXT: [[CALL2:%.*]] = call noundef i32 @_Z3foov.ifunc() +// CHECK-NEXT: [[CALL2:%.*]] = call noundef i32 @_Z3foov() // CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]] // CHECK-NEXT: ret i32 [[ADD3]] // // -// CHECK-LABEL: @_Z3fooi.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 -// CHECK-NEXT: store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4 -// CHECK-NEXT: ret i32 2 +// CHECK-LABEL: @_Z3fooi.resolver( +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 36028797153181696 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 36028797153181696 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @_Z3fooi._Mbf16Msme-f64f64 +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @_Z3fooi.default // // -// CHECK-LABEL: @_Z3foov.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 4 +// CHECK-LABEL: @_Z3foov.resolver( +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 268435488 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 268435488 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @_Z3foov._Msm4Mebf16 +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @_Z3foov.default // // // CHECK-LABEL: @_ZN7MyClass3gooEi._Mdotprod( @@ -144,6 +135,18 @@ int bar() { // CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK-NEXT: ret i32 1 // +// +// CHECK-LABEL: @_Z3fooi.default( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4 +// CHECK-NEXT: ret i32 2 +// +// +// CHECK-LABEL: @_Z3foov.default( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 4 +// //. // CHECK: attributes #[[ATTR0:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme-f64f64" } // CHECK: attributes #[[ATTR1:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fp-armv8,+neon,+sm4" } diff --git a/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp b/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp index 0234e41009f62250998430790e7df16e9733ef48..d9f5e3eacac37d1c474146149e97a558fa45e07c 100644 --- a/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp +++ b/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -triple aarch64-arm-none-eabi %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -triple aarch64 %s -o - | FileCheck %s struct S0 { unsigned int x : 16; diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl index 2b9c66d8fc17a0ec8b9fb0525428b9e3c66a3ec5..74b3f59bf7600fd42d1654b1671e31efbaccc8a6 100644 --- a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl +++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-SPIRV RWBuffer Buf; @@ -7,3 +8,6 @@ RWBuffer Buf; // CHECK: %[[HandleRes:[0-9]+]] = call ptr @llvm.dx.create.handle(i8 1) // CHECK: store ptr %[[HandleRes]], ptr %h, align 4 + +// CHECK-SPIRV: %[[HandleRes:[0-9]+]] = call ptr @llvm.spv.create.handle(i8 1) +// CHECK-SPIRV: store ptr %[[HandleRes]], ptr %h, align 8 diff --git a/clang/test/CodeGenHLSL/shift-mask.hlsl b/clang/test/CodeGenHLSL/shift-mask.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..d046efaf9c1f9c82a3904e1a60fcebfacd3281d5 --- /dev/null +++ b/clang/test/CodeGenHLSL/shift-mask.hlsl @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +int shl32(int V, int S) { + return V << S; +} + +// CHECK: define noundef i32 @"?shl32{{[@$?.A-Za-z0-9_]+}}"(i32 noundef %V, i32 noundef %S) #0 { +// CHECK-DAG: %[[Masked:.*]] = and i32 %{{.*}}, 31 +// CHECK-DAG: %{{.*}} = shl i32 %{{.*}}, %[[Masked]] + +int shr32(int V, int S) { + return V >> S; +} + +// CHECK: define noundef i32 @"?shr32{{[@$?.A-Za-z0-9_]+}}"(i32 noundef %V, i32 noundef %S) #0 { +// CHECK-DAG: %[[Masked:.*]] = and i32 %{{.*}}, 31 +// CHECK-DAG: %{{.*}} = ashr i32 %{{.*}}, %[[Masked]] + +int64_t shl64(int64_t V, int64_t S) { + return V << S; +} + +// CHECK: define noundef i64 @"?shl64{{[@$?.A-Za-z0-9_]+}}"(i64 noundef %V, i64 noundef %S) #0 { +// CHECK-DAG: %[[Masked:.*]] = and i64 %{{.*}}, 63 +// CHECK-DAG: %{{.*}} = shl i64 %{{.*}}, %[[Masked]] + +int64_t shr64(int64_t V, int64_t S) { + return V >> S; +} + +// CHECK: define noundef i64 @"?shr64{{[@$?.A-Za-z0-9_]+}}"(i64 noundef %V, i64 noundef %S) #0 { +// CHECK-DAG: %[[Masked:.*]] = and i64 %{{.*}}, 63 +// CHECK-DAG: %{{.*}} = ashr i64 %{{.*}}, %[[Masked]] diff --git a/clang/test/CodeGenOpenCL/atomic-ops-libcall.cl b/clang/test/CodeGenOpenCL/atomic-ops-libcall.cl index 2f020c210821242a8e45fa943bbfb54cf228cd84..d615ff6bec4140675ace0d5b83fcd0ca759c7d8b 100644 --- a/clang/test/CodeGenOpenCL/atomic-ops-libcall.cl +++ b/clang/test/CodeGenOpenCL/atomic-ops-libcall.cl @@ -20,63 +20,60 @@ typedef enum memory_scope { void f(atomic_int *i, global atomic_int *gi, local atomic_int *li, private atomic_int *pi, atomic_uint *ui, int cmp, int order, int scope) { int x; - // SPIR: {{%[^ ]*}} = call i32 @__opencl_atomic_load_4(ptr addrspace(4) noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) - // ARM: {{%[^ ]*}} = call i32 @__opencl_atomic_load_4(ptr noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) + // SPIR: load atomic i32, ptr addrspace(4) {{.*}} seq_cst, align 4 + // ARM: load atomic i32, ptr {{.*}} seq_cst, align 4 x = __opencl_atomic_load(i, memory_order_seq_cst, memory_scope_work_group); - // SPIR: call void @__opencl_atomic_store_4(ptr addrspace(4) noundef {{%[0-9]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) - // ARM: call void @__opencl_atomic_store_4(ptr noundef {{%[0-9]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) + // SPIR: store atomic i32 {{.*}}, ptr addrspace(4) {{.*}} seq_cst, align 4 + // ARM: store atomic i32 {{.*}}, ptr {{.*}} seq_cst, align 4 __opencl_atomic_store(i, 1, memory_order_seq_cst, memory_scope_work_group); - // SPIR: %[[GP:[0-9]+]] = addrspacecast ptr addrspace(1) {{%[0-9]+}} to ptr addrspace(4) - // SPIR: call void @__opencl_atomic_store_4(ptr addrspace(4) noundef %[[GP]], i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) - // ARM: call void @__opencl_atomic_store_4(ptr noundef {{%[0-9]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) + // SPIR: store atomic i32 {{.*}}, ptr addrspace(1) {{.*}} seq_cst, align 4 + // ARM: store atomic i32 {{.*}}, ptr {{.*}} seq_cst, align 4 __opencl_atomic_store(gi, 1, memory_order_seq_cst, memory_scope_work_group); - // SPIR: %[[GP:[0-9]+]] = addrspacecast ptr addrspace(3) {{%[0-9]+}} to ptr addrspace(4) - // SPIR: call void @__opencl_atomic_store_4(ptr addrspace(4) noundef %[[GP]], i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) - // ARM: call void @__opencl_atomic_store_4(ptr noundef {{%[0-9]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) + // SPIR: store atomic i32 {{.*}}, ptr addrspace(3) {{.*}} seq_cst, align 4 + // ARM: store atomic i32 {{.*}}, ptr {{.*}} seq_cst, align 4 __opencl_atomic_store(li, 1, memory_order_seq_cst, memory_scope_work_group); - // SPIR: %[[GP:[0-9]+]] = addrspacecast ptr {{%[0-9]+}} to ptr addrspace(4) - // SPIR: call void @__opencl_atomic_store_4(ptr addrspace(4) noundef %[[GP]], i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) - // ARM: call void @__opencl_atomic_store_4(ptr noundef {{%[0-9]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) + // SPIR: store atomic i32 {{.*}}, ptr {{.*}} seq_cst, align 4 + // ARM: store atomic i32 {{.*}}, ptr {{.*}} seq_cst, align 4 __opencl_atomic_store(pi, 1, memory_order_seq_cst, memory_scope_work_group); - // SPIR: {{%[^ ]*}} = call i32 @__opencl_atomic_fetch_add_4(ptr addrspace(4) noundef {{%[0-9]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) - // ARM: {{%[^ ]*}} = call i32 @__opencl_atomic_fetch_add_4(ptr noundef {{%[0-9]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) + // SPIR: atomicrmw add ptr addrspace(4) {{.*}}, i32 {{.*}} seq_cst, align 4 + // ARM: atomicrmw add ptr {{.*}}, i32 {{.*}} seq_cst, align 4 x = __opencl_atomic_fetch_add(i, 3, memory_order_seq_cst, memory_scope_work_group); - // SPIR: {{%[^ ]*}} = call i32 @__opencl_atomic_fetch_min_4(ptr addrspace(4) noundef {{%[0-9]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) - // ARM: {{%[^ ]*}} = call i32 @__opencl_atomic_fetch_min_4(ptr noundef {{%[0-9]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) + // SPIR: atomicrmw min ptr addrspace(4) {{.*}}, i32 {{.*}} seq_cst, align 4 + // ARM: atomicrmw min ptr {{.*}}, i32 {{.*}} seq_cst, align 4 x = __opencl_atomic_fetch_min(i, 3, memory_order_seq_cst, memory_scope_work_group); - // SPIR: {{%[^ ]*}} = call i32 @__opencl_atomic_fetch_umin_4(ptr addrspace(4) noundef {{%[0-9]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) - // ARM: {{%[^ ]*}} = call i32 @__opencl_atomic_fetch_umin_4(ptr noundef {{%[0-9]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 1) + // SPIR: atomicrmw umin ptr addrspace(4) {{.*}}, i32 {{.*}} seq_cst, align 4 + // ARM: atomicrmw umin ptr {{.*}}, i32 {{.*}} seq_cst, align 4 x = __opencl_atomic_fetch_min(ui, 3, memory_order_seq_cst, memory_scope_work_group); - // SPIR: {{%[^ ]*}} = call zeroext i1 @__opencl_atomic_compare_exchange_4(ptr addrspace(4) noundef {{%[0-9]+}}, ptr addrspace(4) noundef {{%[^,]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 5, i32 noundef 1) - // ARM: {{%[^ ]*}} = call zeroext i1 @__opencl_atomic_compare_exchange_4(ptr noundef {{%[0-9]+}}, ptr noundef {{%[^,]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 5, i32 noundef 1) + // SPIR: cmpxchg ptr addrspace(4) {{.*}}, i32 {{.*}}, i32 {{.*}} seq_cst seq_cst, align 4 + // ARM: cmpxchg ptr {{.*}}, i32 {{.*}}, i32 {{.*}} seq_cst seq_cst, align 4 x = __opencl_atomic_compare_exchange_strong(i, &cmp, 1, memory_order_seq_cst, memory_order_seq_cst, memory_scope_work_group); - // SPIR: {{%[^ ]*}} = call zeroext i1 @__opencl_atomic_compare_exchange_4(ptr addrspace(4) noundef {{%[0-9]+}}, ptr addrspace(4) noundef {{%[^,]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 5, i32 noundef 1) - // ARM: {{%[^ ]*}} = call zeroext i1 @__opencl_atomic_compare_exchange_4(ptr noundef {{%[0-9]+}}, ptr noundef {{%[^,]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 5, i32 noundef 1) + // SPIR: cmpxchg weak ptr addrspace(4) {{.*}}, i32 {{.*}}, i32 {{.*}} seq_cst seq_cst, align 4 + // ARM: cmpxchg weak ptr {{.*}}, i32 {{.*}}, i32 {{.*}} seq_cst seq_cst, align 4 x = __opencl_atomic_compare_exchange_weak(i, &cmp, 1, memory_order_seq_cst, memory_order_seq_cst, memory_scope_work_group); - // SPIR: {{%[^ ]*}} = call zeroext i1 @__opencl_atomic_compare_exchange_4(ptr addrspace(4) noundef {{%[0-9]+}}, ptr addrspace(4) noundef {{%[^,]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 5, i32 noundef 2) - // ARM: {{%[^ ]*}} = call zeroext i1 @__opencl_atomic_compare_exchange_4(ptr noundef {{%[0-9]+}}, ptr noundef {{%[^,]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 5, i32 noundef 2) + // SPIR: cmpxchg weak ptr addrspace(4) {{.*}}, i32 {{.*}}, i32 {{.*}} seq_cst seq_cst, align 4 + // ARM: cmpxchg weak ptr {{.*}}, i32 {{.*}}, i32 {{.*}} seq_cst seq_cst, align 4 x = __opencl_atomic_compare_exchange_weak(i, &cmp, 1, memory_order_seq_cst, memory_order_seq_cst, memory_scope_device); - // SPIR: {{%[^ ]*}} = call zeroext i1 @__opencl_atomic_compare_exchange_4(ptr addrspace(4) noundef {{%[0-9]+}}, ptr addrspace(4) noundef {{%[^,]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 5, i32 noundef 3) - // ARM: {{%[^ ]*}} = call zeroext i1 @__opencl_atomic_compare_exchange_4(ptr noundef {{%[0-9]+}}, ptr noundef {{%[^,]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 5, i32 noundef 3) + // SPIR: cmpxchg weak ptr addrspace(4) {{.*}}, i32 {{.*}}, i32 {{.*}} seq_cst seq_cst, align 4 + // ARM: cmpxchg weak ptr {{.*}}, i32 {{.*}}, i32 {{.*}} seq_cst seq_cst, align 4 x = __opencl_atomic_compare_exchange_weak(i, &cmp, 1, memory_order_seq_cst, memory_order_seq_cst, memory_scope_all_svm_devices); #ifdef cl_khr_subgroups - // SPIR: {{%[^ ]*}} = call zeroext i1 @__opencl_atomic_compare_exchange_4(ptr addrspace(4) noundef {{%[0-9]+}}, ptr addrspace(4) noundef {{%[^,]+}}, i32 noundef {{%[0-9]+}}, i32 noundef 5, i32 noundef 5, i32 noundef 4) + // SPIR: cmpxchg weak ptr addrspace(4) {{.*}}, i32 {{.*}}, i32 {{.*}} seq_cst seq_cst, align 4 x = __opencl_atomic_compare_exchange_weak(i, &cmp, 1, memory_order_seq_cst, memory_order_seq_cst, memory_scope_sub_group); #endif - // SPIR: {{%[^ ]*}} = call zeroext i1 @__opencl_atomic_compare_exchange_4(ptr addrspace(4) noundef {{%[0-9]+}}, ptr addrspace(4) noundef {{%[^,]+}}, i32 noundef {{%[0-9]+}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}) - // ARM: {{%[^ ]*}} = call zeroext i1 @__opencl_atomic_compare_exchange_4(ptr noundef {{%[0-9]+}}, ptr noundef {{%[^,]+}}, i32 noundef {{%[0-9]+}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}) + // SPIR: cmpxchg weak ptr addrspace(4) {{.*}}, i32 {{.*}}, i32 {{.*}} seq_cst seq_cst, align 4 + // ARM: cmpxchg weak ptr {{.*}}, i32 {{.*}}, i32 {{.*}} seq_cst seq_cst, align 4 x = __opencl_atomic_compare_exchange_weak(i, &cmp, 1, order, order, scope); } diff --git a/clang/test/CodeGenOpenCL/reflect.cl b/clang/test/CodeGenOpenCL/reflect.cl new file mode 100644 index 0000000000000000000000000000000000000000..9ae4a5f027d358c7dcaf8a688cdf338558da1474 --- /dev/null +++ b/clang/test/CodeGenOpenCL/reflect.cl @@ -0,0 +1,28 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// RUN: %clang_cc1 %s -triple nvptx-unknown-unknown -emit-llvm -O0 -o - | FileCheck %s + +// CHECK-LABEL: define dso_local zeroext i1 @device_function( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.nvvm.reflect(ptr addrspacecast (ptr addrspace(4) @.str to ptr)) +// CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[TMP0]], 700 +// CHECK-NEXT: ret i1 [[CMP]] +// +bool device_function() { + return __nvvm_reflect("__CUDA_ARCH") >= 700; +} + +// CHECK-LABEL: define dso_local spir_kernel void @kernel_function( +// CHECK-SAME: ptr addrspace(1) noundef align 4 [[I:%.*]]) #[[ATTR2:[0-9]+]] !kernel_arg_addr_space !4 !kernel_arg_access_qual !5 !kernel_arg_type !6 !kernel_arg_base_type !6 !kernel_arg_type_qual !7 { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca ptr addrspace(1), align 4 +// CHECK-NEXT: store ptr addrspace(1) [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[CALL:%.*]] = call zeroext i1 @device_function() #[[ATTR3:[0-9]+]] +// CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CALL]] to i32 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr [[I_ADDR]], align 4 +// CHECK-NEXT: store i32 [[CONV]], ptr addrspace(1) [[TMP0]], align 4 +// CHECK-NEXT: ret void +// +__kernel void kernel_function(__global int *i) { + *i = device_function(); +} diff --git a/clang/test/Driver/aarch64-cssc.c b/clang/test/Driver/aarch64-cssc.c index a3e18663279bbd0af000ec9af7451f7a07b3fb41..5df0ea79d7c8508d089c2af44e5d35e3e09e5be6 100644 --- a/clang/test/Driver/aarch64-cssc.c +++ b/clang/test/Driver/aarch64-cssc.c @@ -9,6 +9,7 @@ // RUN: %clang -S -o - -emit-llvm --target=aarch64-none-elf -march=armv9.4-a %s 2>&1 | FileCheck %s // RUN: %clang -S -o - -emit-llvm --target=aarch64-none-elf -march=armv9.4-a+cssc %s 2>&1 | FileCheck %s // RUN: %clang -S -o - -emit-llvm --target=aarch64-none-elf -march=armv9.4-a+nocssc %s 2>&1 | FileCheck %s --check-prefix=NO_CSSC +// RUN: %clang -S -o - -emit-llvm --target=aarch64-none-elf -mcpu=ampere1b %s 2>&1 | FileCheck %s // CHECK: "target-features"="{{.*}},+cssc // NO_CSSC: "target-features"="{{.*}},-cssc diff --git a/clang/test/Driver/aarch64-fix-cortex-a53-835769.c b/clang/test/Driver/aarch64-fix-cortex-a53-835769.c index d7a2ad9112611b43fc4db7776f4e2ef44e82136a..84d8c1dde7a7890f39a331b9dae5dcf2fc65c0bb 100644 --- a/clang/test/Driver/aarch64-fix-cortex-a53-835769.c +++ b/clang/test/Driver/aarch64-fix-cortex-a53-835769.c @@ -1,8 +1,8 @@ -// RUN: %clang --target=aarch64-linux-eabi %s -### 2>&1 \ +// RUN: %clang --target=aarch64 %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-DEF %s -// RUN: %clang --target=aarch64-linux-eabi -mfix-cortex-a53-835769 %s -### 2>&1 \ +// RUN: %clang --target=aarch64 -mfix-cortex-a53-835769 %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-YES %s -// RUN: %clang --target=aarch64-linux-eabi -mno-fix-cortex-a53-835769 %s -### 2>&1 \ +// RUN: %clang --target=aarch64 -mno-fix-cortex-a53-835769 %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO %s // RUN: %clang --target=aarch64-linux-androideabi %s -### 2>&1 \ diff --git a/clang/test/Driver/aarch64-mgeneral_regs_only.c b/clang/test/Driver/aarch64-mgeneral_regs_only.c index 17da9c614a8a1b1e36447b966feefa14e83a4997..93f1ca95826d8c05d557f2f4a2698eebe63d512b 100644 --- a/clang/test/Driver/aarch64-mgeneral_regs_only.c +++ b/clang/test/Driver/aarch64-mgeneral_regs_only.c @@ -1,6 +1,6 @@ // Test the -mgeneral-regs-only option -// RUN: %clang --target=aarch64-linux-eabi -mgeneral-regs-only %s -### 2>&1 \ +// RUN: %clang --target=aarch64 -mgeneral-regs-only %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-FP %s // RUN: %clang --target=arm64-linux-eabi -mgeneral-regs-only %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-FP %s diff --git a/clang/test/Driver/aarch64-pauth-lr.c b/clang/test/Driver/aarch64-pauth-lr.c index 2e1b530fc9895b5278d59c685ae63a3464c1185e..00281fabba5550a15e457acfd7bc633e92f8db53 100644 --- a/clang/test/Driver/aarch64-pauth-lr.c +++ b/clang/test/Driver/aarch64-pauth-lr.c @@ -1,15 +1,15 @@ // Check the -cc1 flags for the various forms of -mbranch-protection=pac-ret+pc. -// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR -// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+b-key 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-B-KEY -// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+leaf 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-LEAF -// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+bti 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-BTI -// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+leaf+b-key+bti 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-LEAF-B-KEY-BTI -// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc -march=armv9.5-a 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR -// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+b-key -march=armv9.5-a 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-B-KEY -// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+leaf -march=armv9.5-a 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-LEAF -// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+bti -march=armv9.5-a 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-BTI -// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+leaf+b-key+bti -march=armv9.5-a 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-LEAF-B-KEY-BTI +// RUN: %clang --target=aarch64 -c %s -### -mbranch-protection=pac-ret+pc 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR +// RUN: %clang --target=aarch64 -c %s -### -mbranch-protection=pac-ret+pc+b-key 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-B-KEY +// RUN: %clang --target=aarch64 -c %s -### -mbranch-protection=pac-ret+pc+leaf 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-LEAF +// RUN: %clang --target=aarch64 -c %s -### -mbranch-protection=pac-ret+pc+bti 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-BTI +// RUN: %clang --target=aarch64 -c %s -### -mbranch-protection=pac-ret+pc+leaf+b-key+bti 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-LEAF-B-KEY-BTI +// RUN: %clang --target=aarch64 -c %s -### -mbranch-protection=pac-ret+pc -march=armv9.5-a 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR +// RUN: %clang --target=aarch64 -c %s -### -mbranch-protection=pac-ret+pc+b-key -march=armv9.5-a 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-B-KEY +// RUN: %clang --target=aarch64 -c %s -### -mbranch-protection=pac-ret+pc+leaf -march=armv9.5-a 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-LEAF +// RUN: %clang --target=aarch64 -c %s -### -mbranch-protection=pac-ret+pc+bti -march=armv9.5-a 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-BTI +// RUN: %clang --target=aarch64 -c %s -### -mbranch-protection=pac-ret+pc+leaf+b-key+bti -march=armv9.5-a 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-LEAF-B-KEY-BTI // PAUTH-LR: "-msign-return-address=non-leaf" "-msign-return-address-key=a_key" "-mbranch-protection-pauth-lr" // PAUTH-LR-B-KEY: "-msign-return-address=non-leaf" "-msign-return-address-key=b_key" "-mbranch-protection-pauth-lr" diff --git a/clang/test/Driver/aarch64-target-as-march.s b/clang/test/Driver/aarch64-target-as-march.s index 59c0ca41cbe24c6fd20c01ccd111191aed90ffa3..ae77d08c5ecc4f3437b764d6339e55c336098890 100644 --- a/clang/test/Driver/aarch64-target-as-march.s +++ b/clang/test/Driver/aarch64-target-as-march.s @@ -2,42 +2,42 @@ /// via -Wa or -Xassembler are applied correctly to assembler inputs. /// Does not apply to non assembly files -// RUN: %clang --target=aarch64-linux-gnueabi -### -c -Wa,-march=armv8.1-a \ +// RUN: %clang --target=aarch64 -### -c -Wa,-march=armv8.1-a \ // RUN: %S/Inputs/wildcard1.c 2>&1 | FileCheck --check-prefix=TARGET-FEATURE-1 %s -// RUN: %clang --target=aarch64-linux-gnueabi -### -c -Xassembler -march=armv8.1-a \ +// RUN: %clang --target=aarch64 -### -c -Xassembler -march=armv8.1-a \ // RUN: %S/Inputs/wildcard1.c 2>&1 | FileCheck --check-prefix=TARGET-FEATURE-1 %s // TARGET-FEATURE-1-NOT: "-target-feature" "+v8.1a" /// Does apply to assembler input -// RUN: %clang --target=aarch64-linux-gnueabi -### -c -Wa,-march=armv8.2-a %s 2>&1 | \ +// RUN: %clang --target=aarch64 -### -c -Wa,-march=armv8.2-a %s 2>&1 | \ // RUN: FileCheck --check-prefix=TARGET-FEATURE-2 %s -// RUN: %clang --target=aarch64-linux-gnueabi -### -c -Xassembler -march=armv8.2-a %s 2>&1 | \ +// RUN: %clang --target=aarch64 -### -c -Xassembler -march=armv8.2-a %s 2>&1 | \ // RUN: FileCheck --check-prefix=TARGET-FEATURE-2 %s // TARGET-FEATURE-2: "-target-feature" "+v8.2a" /// No unused argument warnings when there are multiple values -// RUN: %clang --target=aarch64-linux-gnueabi -### -c -Wa,-march=armv8.1-a -Wa,-march=armv8.2-a %s 2>&1 | \ +// RUN: %clang --target=aarch64 -### -c -Wa,-march=armv8.1-a -Wa,-march=armv8.2-a %s 2>&1 | \ // RUN: FileCheck --check-prefix=UNUSED-WARNING %s // UNUSED-WARNING-NOT: warning: argument unused during compilation /// Last march to assembler wins -// RUN: %clang --target=aarch64-linux-gnueabi -### -c -Wa,-march=armv8.2-a -Wa,-march=armv8.1-a %s 2>&1 | \ +// RUN: %clang --target=aarch64 -### -c -Wa,-march=armv8.2-a -Wa,-march=armv8.1-a %s 2>&1 | \ // RUN: FileCheck --check-prefix=MULTIPLE-VALUES %s -// RUN: %clang --target=aarch64-linux-gnueabi -### -c -Wa,-march=armv8.2-a,-march=armv8.1-a %s 2>&1 | \ +// RUN: %clang --target=aarch64 -### -c -Wa,-march=armv8.2-a,-march=armv8.1-a %s 2>&1 | \ // RUN: FileCheck --check-prefix=MULTIPLE-VALUES %s -// RUN: %clang --target=aarch64-linux-gnueabi -### -c -Xassembler -march=armv8.2-a -Xassembler \ +// RUN: %clang --target=aarch64 -### -c -Xassembler -march=armv8.2-a -Xassembler \ // RUN: -march=armv8.1-a %s 2>&1 | FileCheck --check-prefix=MULTIPLE-VALUES %s // MULTIPLE-VALUES: "-target-feature" "+v8.1a // MULTIPLE-VALUES-NOT: "-target-feature" "+v8.2a /// march to compiler and assembler, we choose the one suited to the input file type -// RUN: %clang --target=aarch64-linux-gnueabi -### -c -Wa,-march=armv8.3-a -march=armv8.4-a %s 2>&1 | \ +// RUN: %clang --target=aarch64 -### -c -Wa,-march=armv8.3-a -march=armv8.4-a %s 2>&1 | \ // RUN: FileCheck --check-prefix=TARGET-FEATURE-3 %s -// RUN: %clang --target=aarch64-linux-gnueabi -### -c -Wa,-march=armv8.3-a -march=armv8.4-a \ +// RUN: %clang --target=aarch64 -### -c -Wa,-march=armv8.3-a -march=armv8.4-a \ // RUN: %S/Inputs/wildcard1.c 2>&1 | FileCheck --check-prefix=TARGET-FEATURE-4 %s // TARGET-FEATURE-3: "-target-feature" "+v8.3a" @@ -46,9 +46,9 @@ // TARGET-FEATURE-4-NOT: "-target-feature" "+v8.3a" // Invalid -march settings -// RUN: not %clang --target=aarch64-linux-gnueabi -### -c -Wa,-march=all %s 2>&1 | \ +// RUN: not %clang --target=aarch64 -### -c -Wa,-march=all %s 2>&1 | \ // RUN: FileCheck --check-prefix=INVALID-ARCH-1 %s -// RUN: not %clang --target=aarch64-linux-gnueabi -### -c -Wa,-march=foobar %s 2>&1 | \ +// RUN: not %clang --target=aarch64 -### -c -Wa,-march=foobar %s 2>&1 | \ // RUN: FileCheck --check-prefix=INVALID-ARCH-2 %s // INVALID-ARCH-1: error: unsupported argument 'all' to option '-march=' diff --git a/clang/test/Driver/amdgpu-macros.cl b/clang/test/Driver/amdgpu-macros.cl index 81c22af460d12d0e87dcfc0c1bfb4c4e921a397c..3b10444ef71d36fae1c5280c54458196fc19c10b 100644 --- a/clang/test/Driver/amdgpu-macros.cl +++ b/clang/test/Driver/amdgpu-macros.cl @@ -131,6 +131,11 @@ // RUN: %clang -E -dM -target amdgcn -mcpu=gfx1200 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1200 -DFAMILY=GFX12 // RUN: %clang -E -dM -target amdgcn -mcpu=gfx1201 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1201 -DFAMILY=GFX12 +// RUN: %clang -E -dM -target amdgcn -mcpu=gfx9-generic %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=64 -DCPU=gfx9_generic -DFAMILY=GFX9 +// RUN: %clang -E -dM -target amdgcn -mcpu=gfx10.1-generic %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx10_1_generic -DFAMILY=GFX10 +// RUN: %clang -E -dM -target amdgcn -mcpu=gfx10.3-generic %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx10_3_generic -DFAMILY=GFX10 +// RUN: %clang -E -dM -target amdgcn -mcpu=gfx11-generic %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx11_generic -DFAMILY=GFX11 + // ARCH-GCN-DAG: #define FP_FAST_FMA 1 // FAST_FMAF-DAG: #define FP_FAST_FMAF 1 diff --git a/clang/test/Driver/amdgpu-mcpu.cl b/clang/test/Driver/amdgpu-mcpu.cl index eeb16ae98ebad7b1ef769cb5719cfa631cd1a323..6f18ea0615cb69d80e09f77747899c9c01c83aa8 100644 --- a/clang/test/Driver/amdgpu-mcpu.cl +++ b/clang/test/Driver/amdgpu-mcpu.cl @@ -115,6 +115,11 @@ // RUN: %clang -### -target amdgcn -mcpu=gfx1200 %s 2>&1 | FileCheck --check-prefix=GFX1200 %s // RUN: %clang -### -target amdgcn -mcpu=gfx1201 %s 2>&1 | FileCheck --check-prefix=GFX1201 %s +// RUN: %clang -### -target amdgcn -mcpu=gfx9-generic %s 2>&1 | FileCheck --check-prefix=GFX9_GENERIC %s +// RUN: %clang -### -target amdgcn -mcpu=gfx10.1-generic %s 2>&1 | FileCheck --check-prefix=GFX10_1_GENERIC %s +// RUN: %clang -### -target amdgcn -mcpu=gfx10.3-generic %s 2>&1 | FileCheck --check-prefix=GFX10_3_GENERIC %s +// RUN: %clang -### -target amdgcn -mcpu=gfx11-generic %s 2>&1 | FileCheck --check-prefix=GFX11_GENERIC %s + // GCNDEFAULT-NOT: -target-cpu // GFX600: "-target-cpu" "gfx600" // GFX601: "-target-cpu" "gfx601" @@ -160,3 +165,8 @@ // GFX1151: "-target-cpu" "gfx1151" // GFX1200: "-target-cpu" "gfx1200" // GFX1201: "-target-cpu" "gfx1201" + +// GFX9_GENERIC: "-target-cpu" "gfx9-generic" +// GFX10_1_GENERIC: "-target-cpu" "gfx10.1-generic" +// GFX10_3_GENERIC: "-target-cpu" "gfx10.3-generic" +// GFX11_GENERIC: "-target-cpu" "gfx11-generic" diff --git a/clang/test/Driver/arm-alignment.c b/clang/test/Driver/arm-alignment.c index ba1be29bb7d1be423e57c7529ac2e9e9c6c0706d..9177b625729b85842ecebb20264bc5039b2f436e 100644 --- a/clang/test/Driver/arm-alignment.c +++ b/clang/test/Driver/arm-alignment.c @@ -22,13 +22,13 @@ // RUN: %clang -target armv7-windows -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-UNALIGNED-ARM < %t %s -// RUN: %clang -target aarch64-none-gnueabi -munaligned-access -### %s 2> %t +// RUN: %clang --target=aarch64 -munaligned-access -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-UNALIGNED-AARCH64 < %t %s -// RUN: %clang -target aarch64-none-gnueabi -mstrict-align -munaligned-access -### %s 2> %t +// RUN: %clang --target=aarch64 -mstrict-align -munaligned-access -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-UNALIGNED-AARCH64 < %t %s -// RUN: %clang -target aarch64-none-gnueabi -mno-unaligned-access -munaligned-access -### %s 2> %t +// RUN: %clang --target=aarch64 -mno-unaligned-access -munaligned-access -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-UNALIGNED-AARCH64 < %t %s // CHECK-UNALIGNED-ARM-NOT: "-target-feature" "+strict-align" @@ -68,19 +68,19 @@ // RUN: %clang -target armv6m-netbsd-eabi -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-ALIGNED-ARM < %t %s -// RUN: %clang -target aarch64-none-gnueabi -mno-unaligned-access -### %s 2> %t +// RUN: %clang --target=aarch64 -mno-unaligned-access -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-ALIGNED-AARCH64 < %t %s -// RUN: %clang -target aarch64-none-gnueabi -mstrict-align -### %s 2> %t +// RUN: %clang --target=aarch64 -mstrict-align -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-ALIGNED-AARCH64 < %t %s -// RUN: %clang -target aarch64-none-gnueabi -munaligned-access -mno-unaligned-access -### %s 2> %t +// RUN: %clang --target=aarch64 -munaligned-access -mno-unaligned-access -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-ALIGNED-AARCH64 < %t %s -// RUN: %clang -target aarch64-none-gnueabi -munaligned-access -mstrict-align -### %s 2> %t +// RUN: %clang --target=aarch64 -munaligned-access -mstrict-align -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-ALIGNED-AARCH64 < %t %s -// RUN: %clang -target aarch64-none-gnueabi -mkernel -mno-unaligned-access -### %s 2> %t +// RUN: %clang --target=aarch64 -mkernel -mno-unaligned-access -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-ALIGNED-AARCH64 < %t %s // RUN: %clang -target aarch64-unknown-openbsd -### %s 2> %t diff --git a/clang/test/Driver/arm-no-neg-immediates.c b/clang/test/Driver/arm-no-neg-immediates.c index f1e4d5f7906b8280f165eb7b7fe0a54db3d828cf..26c70c87a74c119ea7ca05958e2a6c4c9126a223 100644 --- a/clang/test/Driver/arm-no-neg-immediates.c +++ b/clang/test/Driver/arm-no-neg-immediates.c @@ -1,8 +1,8 @@ // RUN: %clang -target arm-none-gnueabi -### %s 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT // RUN: %clang -target arm-none-gnueabi -mno-neg-immediates -### %s 2>&1 | FileCheck %s -// RUN: %clang -target aarch64-none-gnueabi -### %s 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT -// RUN: %clang -target aarch64-none-gnueabi -mno-neg-immediates -### %s 2>&1 | FileCheck %s +// RUN: %clang --target=aarch64 -### %s 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT +// RUN: %clang --target=aarch64 -mno-neg-immediates -### %s 2>&1 | FileCheck %s // CHECK: "-target-feature" "+no-neg-immediates" // CHECK-DEFAULT-NOT: "+no-neg-immediates" diff --git a/clang/test/Driver/hlsl-lang-targets.hlsl b/clang/test/Driver/hlsl-lang-targets.hlsl index f2f4bba8196bc962834623992a0ac41c22cc6564..7ce490a66df5f5bd415b66f542afca352498f7eb 100644 --- a/clang/test/Driver/hlsl-lang-targets.hlsl +++ b/clang/test/Driver/hlsl-lang-targets.hlsl @@ -32,7 +32,7 @@ // Invalid shader stages // // RUN: not %clang -target dxil--shadermodel6.2-unknown %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s -// RUN: not %clang -target dxil--shadermodel6.2-invalidenvironment %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s +// RUN: not %clang --target=dxil--shadermodel6.2-invalidenvironment %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV-DRV %s // RUN: not %clang -target dxil--shadermodel6.2-eabi %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s // RUN: not %clang -target dxil--shadermodel6.2-msvc %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s @@ -47,6 +47,7 @@ // CHECK-BAD-OS: error: shader model '{{.*}}' in target '{{.*}}' is invalid for HLSL code generation // CHECK-NO-ENV: error: shader stage is required as environment in target '{{.*}}' for HLSL code generation // CHECK-BAD-ENV: error: shader stage '{{.*}}' in target '{{.*}}' is invalid for HLSL code generation +// CHECK-BAD-ENV-DRV: error: version '{{.*}}' in target triple '{{.*}}' is invalid // CHECK-BAD-TARGET: error: HLSL code generation is unsupported for target '{{.*}}' [shader("pixel")] diff --git a/clang/test/Driver/linker-wrapper.c b/clang/test/Driver/linker-wrapper.c index 010001b83d7c2de669058304aa99a54903b03aca..7fd46778ac9102d7886d107f36f68220c37669af 100644 --- a/clang/test/Driver/linker-wrapper.c +++ b/clang/test/Driver/linker-wrapper.c @@ -172,6 +172,22 @@ __attribute__((visibility("protected"), used)) int x; // AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx90a:xnack+ -O2 -Wl,--no-undefined {{.*}}.o {{.*}}.o // AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx90a:xnack- -O2 -Wl,--no-undefined {{.*}}.o {{.*}}.o +// RUN: clang-offload-packager -o %t-lib.out \ +// RUN: --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=generic +// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t-lib.out +// RUN: llvm-ar rcs %t.a %t.o +// RUN: clang-offload-packager -o %t1.out \ +// RUN: --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx90a +// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t1.o -fembed-offload-object=%t1.out +// RUN: clang-offload-packager -o %t2.out \ +// RUN: --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx908 +// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t2.o -fembed-offload-object=%t2.out +// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \ +// RUN: --linker-path=/usr/bin/ld -- %t1.o %t2.o %t.a -o a.out 2>&1 | FileCheck %s --check-prefix=ARCH-ALL + +// ARCH-ALL: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx908 -O2 -Wl,--no-undefined {{.*}}.o {{.*}}.o +// ARCH-ALL: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx90a -O2 -Wl,--no-undefined {{.*}}.o {{.*}}.o + // RUN: clang-offload-packager -o %t.out \ // RUN: --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu \ // RUN: --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c index b8efd64cd91f0eaba1e72960bdd122d2c649ceb8..b3ce5ca307a6c3eb2fcbb59c377fd71bcdf2bc1a 100644 --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -1750,10 +1750,10 @@ // RUN: --target=armv7eb-pc-linux-musleabi -mhard-float \ // RUN: | FileCheck --check-prefix=CHECK-MUSL-ARMEBHF %s // RUN: %clang -### %s -no-pie 2>&1 \ -// RUN: --target=aarch64-pc-linux-musleabi \ +// RUN: --target=aarch64-pc-linux-musl \ // RUN: | FileCheck --check-prefix=CHECK-MUSL-AARCH64 %s // RUN: %clang -### %s -no-pie 2>&1 \ -// RUN: --target=aarch64_be-pc-linux-musleabi \ +// RUN: --target=aarch64_be-pc-linux-musl \ // RUN: | FileCheck --check-prefix=CHECK-MUSL-AARCH64_BE %s // CHECK-MUSL-X86: "-dynamic-linker" "/lib/ld-musl-i386.so.1" // CHECK-MUSL-X86_64: "-dynamic-linker" "/lib/ld-musl-x86_64.so.1" diff --git a/clang/test/Driver/riscv-features.c b/clang/test/Driver/riscv-features.c index d3700f71aa7e1de011599f39f01bcc37d7293629..a108383e29fb6be669f9a2f792de708b5d61c643 100644 --- a/clang/test/Driver/riscv-features.c +++ b/clang/test/Driver/riscv-features.c @@ -27,6 +27,12 @@ // DEFAULT-NOT: "-target-feature" "-save-restore" // DEFAULT-NOT: "-target-feature" "+save-restore" +// RUN: %clang --target=riscv32-unknown-elf -### %s -mforced-sw-shadow-stack 2>&1 | FileCheck %s -check-prefix=FORCE-SW-SCS +// RUN: %clang --target=riscv32-unknown-elf -### %s -mno-forced-sw-shadow-stack 2>&1 | FileCheck %s -check-prefix=NO-FORCE-SW-SCS +// FORCE-SW-SCS: "-target-feature" "+forced-sw-shadow-stack" +// NO-FORCE-SW-SCS: "-target-feature" "-forced-sw-shadow-stack" +// DEFAULT-NOT: "-target-feature" "+forced-sw-shadow-stack" + // RUN: %clang --target=riscv32-unknown-elf -### %s -munaligned-access 2>&1 | FileCheck %s -check-prefix=FAST-UNALIGNED-ACCESS // RUN: %clang --target=riscv32-unknown-elf -### %s -mno-unaligned-access 2>&1 | FileCheck %s -check-prefix=NO-FAST-UNALIGNED-ACCESS // RUN: %clang --target=riscv32-unknown-elf -### %s -mno-strict-align 2>&1 | FileCheck %s -check-prefix=FAST-UNALIGNED-ACCESS diff --git a/clang/test/Driver/sparc-fixed-register.c b/clang/test/Driver/sparc-fixed-register.c new file mode 100644 index 0000000000000000000000000000000000000000..24880b9c9d86fddb2c50c2a7b16f04d9c8ab74ed --- /dev/null +++ b/clang/test/Driver/sparc-fixed-register.c @@ -0,0 +1,181 @@ +// RUN: %clang --target=sparc-none-gnu -ffixed-g1 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-G1 < %t %s +// CHECK-FIXED-G1: "-target-feature" "+reserve-g1" + +// RUN: %clang --target=sparc-none-gnu -ffixed-g2 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-G2 < %t %s +// CHECK-FIXED-G2: "-target-feature" "+reserve-g2" + +// RUN: %clang --target=sparc-none-gnu -ffixed-g3 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-G3 < %t %s +// CHECK-FIXED-G3: "-target-feature" "+reserve-g3" + +// RUN: %clang --target=sparc-none-gnu -ffixed-g4 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-G4 < %t %s +// CHECK-FIXED-G4: "-target-feature" "+reserve-g4" + +// RUN: %clang --target=sparc-none-gnu -ffixed-g5 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-G5 < %t %s +// CHECK-FIXED-G5: "-target-feature" "+reserve-g5" + +// RUN: %clang --target=sparc-none-gnu -ffixed-g6 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-G6 < %t %s +// CHECK-FIXED-G6: "-target-feature" "+reserve-g6" + +// RUN: %clang --target=sparc-none-gnu -ffixed-g7 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-G7 < %t %s +// CHECK-FIXED-G7: "-target-feature" "+reserve-g7" + +// RUN: %clang --target=sparc-none-gnu -ffixed-o0 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-O0 < %t %s +// CHECK-FIXED-O0: "-target-feature" "+reserve-o0" + +// RUN: %clang --target=sparc-none-gnu -ffixed-o1 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-O1 < %t %s +// CHECK-FIXED-O1: "-target-feature" "+reserve-o1" + +// RUN: %clang --target=sparc-none-gnu -ffixed-o2 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-O2 < %t %s +// CHECK-FIXED-O2: "-target-feature" "+reserve-o2" + +// RUN: %clang --target=sparc-none-gnu -ffixed-o3 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-O3 < %t %s +// CHECK-FIXED-O3: "-target-feature" "+reserve-o3" + +// RUN: %clang --target=sparc-none-gnu -ffixed-o4 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-O4 < %t %s +// CHECK-FIXED-O4: "-target-feature" "+reserve-o4" + +// RUN: %clang --target=sparc-none-gnu -ffixed-o5 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-O5 < %t %s +// CHECK-FIXED-O5: "-target-feature" "+reserve-o5" + +// RUN: %clang --target=sparc-none-gnu -ffixed-l0 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-L0 < %t %s +// CHECK-FIXED-L0: "-target-feature" "+reserve-l0" + +// RUN: %clang --target=sparc-none-gnu -ffixed-l1 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-L1 < %t %s +// CHECK-FIXED-L1: "-target-feature" "+reserve-l1" + +// RUN: %clang --target=sparc-none-gnu -ffixed-l2 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-L2 < %t %s +// CHECK-FIXED-L2: "-target-feature" "+reserve-l2" + +// RUN: %clang --target=sparc-none-gnu -ffixed-l3 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-L3 < %t %s +// CHECK-FIXED-L3: "-target-feature" "+reserve-l3" + +// RUN: %clang --target=sparc-none-gnu -ffixed-l4 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-L4 < %t %s +// CHECK-FIXED-L4: "-target-feature" "+reserve-l4" + +// RUN: %clang --target=sparc-none-gnu -ffixed-l5 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-L5 < %t %s +// CHECK-FIXED-L5: "-target-feature" "+reserve-l5" + +// RUN: %clang --target=sparc-none-gnu -ffixed-l6 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-L6 < %t %s +// CHECK-FIXED-L6: "-target-feature" "+reserve-l6" + +// RUN: %clang --target=sparc-none-gnu -ffixed-l7 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-L7 < %t %s +// CHECK-FIXED-L7: "-target-feature" "+reserve-l7" + +// RUN: %clang --target=sparc-none-gnu -ffixed-i0 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-I0 < %t %s +// CHECK-FIXED-I0: "-target-feature" "+reserve-i0" + +// RUN: %clang --target=sparc-none-gnu -ffixed-i1 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-I1 < %t %s +// CHECK-FIXED-I1: "-target-feature" "+reserve-i1" + +// RUN: %clang --target=sparc-none-gnu -ffixed-i2 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-I2 < %t %s +// CHECK-FIXED-I2: "-target-feature" "+reserve-i2" + +// RUN: %clang --target=sparc-none-gnu -ffixed-i3 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-I3 < %t %s +// CHECK-FIXED-I3: "-target-feature" "+reserve-i3" + +// RUN: %clang --target=sparc-none-gnu -ffixed-i4 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-I4 < %t %s +// CHECK-FIXED-I4: "-target-feature" "+reserve-i4" + +// RUN: %clang --target=sparc-none-gnu -ffixed-i5 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-I5 < %t %s +// CHECK-FIXED-I5: "-target-feature" "+reserve-i5" + +// Test multiple of reserve-* options together. +// RUN: %clang --target=sparc-none-gnu \ +// RUN: -ffixed-g1 \ +// RUN: -ffixed-o2 \ +// RUN: -ffixed-l3 \ +// RUN: -ffixed-i4 \ +// RUN: -### %s 2> %t +// RUN: FileCheck \ +// RUN: --check-prefix=CHECK-FIXED-G1 \ +// RUN: --check-prefix=CHECK-FIXED-O2 \ +// RUN: --check-prefix=CHECK-FIXED-L3 \ +// RUN: --check-prefix=CHECK-FIXED-I4 \ +// RUN: < %t %s + +// Test all reserve-* options together. +// RUN: %clang --target=sparc-none-gnu \ +// RUN: -ffixed-g1 \ +// RUN: -ffixed-g2 \ +// RUN: -ffixed-g3 \ +// RUN: -ffixed-g4 \ +// RUN: -ffixed-g5 \ +// RUN: -ffixed-g6 \ +// RUN: -ffixed-g7 \ +// RUN: -ffixed-o0 \ +// RUN: -ffixed-o1 \ +// RUN: -ffixed-o2 \ +// RUN: -ffixed-o3 \ +// RUN: -ffixed-o4 \ +// RUN: -ffixed-o5 \ +// RUN: -ffixed-l0 \ +// RUN: -ffixed-l1 \ +// RUN: -ffixed-l2 \ +// RUN: -ffixed-l3 \ +// RUN: -ffixed-l4 \ +// RUN: -ffixed-l5 \ +// RUN: -ffixed-l6 \ +// RUN: -ffixed-l7 \ +// RUN: -ffixed-i0 \ +// RUN: -ffixed-i1 \ +// RUN: -ffixed-i2 \ +// RUN: -ffixed-i3 \ +// RUN: -ffixed-i4 \ +// RUN: -ffixed-i5 \ +// RUN: -### %s 2> %t +// RUN: FileCheck \ +// RUN: --check-prefix=CHECK-FIXED-G1 \ +// RUN: --check-prefix=CHECK-FIXED-G2 \ +// RUN: --check-prefix=CHECK-FIXED-G3 \ +// RUN: --check-prefix=CHECK-FIXED-G4 \ +// RUN: --check-prefix=CHECK-FIXED-G5 \ +// RUN: --check-prefix=CHECK-FIXED-G6 \ +// RUN: --check-prefix=CHECK-FIXED-G7 \ +// RUN: --check-prefix=CHECK-FIXED-O0 \ +// RUN: --check-prefix=CHECK-FIXED-O1 \ +// RUN: --check-prefix=CHECK-FIXED-O2 \ +// RUN: --check-prefix=CHECK-FIXED-O3 \ +// RUN: --check-prefix=CHECK-FIXED-O4 \ +// RUN: --check-prefix=CHECK-FIXED-O5 \ +// RUN: --check-prefix=CHECK-FIXED-L0 \ +// RUN: --check-prefix=CHECK-FIXED-L1 \ +// RUN: --check-prefix=CHECK-FIXED-L2 \ +// RUN: --check-prefix=CHECK-FIXED-L3 \ +// RUN: --check-prefix=CHECK-FIXED-L4 \ +// RUN: --check-prefix=CHECK-FIXED-L5 \ +// RUN: --check-prefix=CHECK-FIXED-L6 \ +// RUN: --check-prefix=CHECK-FIXED-L7 \ +// RUN: --check-prefix=CHECK-FIXED-I0 \ +// RUN: --check-prefix=CHECK-FIXED-I1 \ +// RUN: --check-prefix=CHECK-FIXED-I2 \ +// RUN: --check-prefix=CHECK-FIXED-I3 \ +// RUN: --check-prefix=CHECK-FIXED-I4 \ +// RUN: --check-prefix=CHECK-FIXED-I5 \ +// RUN: < %t %s diff --git a/clang/test/Driver/tls-dialect.c b/clang/test/Driver/tls-dialect.c index 4e105ce3cea5d9425137297aed0858c4ebc7bd0e..f73915b28ec2a301f8b8f32ece70e605cf0f80ca 100644 --- a/clang/test/Driver/tls-dialect.c +++ b/clang/test/Driver/tls-dialect.c @@ -3,6 +3,10 @@ // RUN: %clang -### --target=riscv64-linux %s 2>&1 | FileCheck --check-prefix=NODESC %s // RUN: %clang -### --target=x86_64-linux -mtls-dialect=gnu %s 2>&1 | FileCheck --check-prefix=NODESC %s +/// Android supports TLSDESC by default on RISC-V +/// TLSDESC is not on by default in Linux, even on RISC-V, and is covered above +// RUN: %clang -### --target=riscv64-android %s 2>&1 | FileCheck --check-prefix=DESC %s + /// LTO // RUN: %clang -### --target=riscv64-linux -flto -mtls-dialect=desc %s 2>&1 | FileCheck --check-prefix=LTO-DESC %s // RUN: %clang -### --target=riscv64-linux -flto %s 2>&1 | FileCheck --check-prefix=LTO-NODESC %s diff --git a/clang/test/Driver/xros-driver-requires-darwin-host.c b/clang/test/Driver/xros-driver-requires-darwin-host.c new file mode 100644 index 0000000000000000000000000000000000000000..e5bfccae2c20922675d58646d2bc644a2ca9723d --- /dev/null +++ b/clang/test/Driver/xros-driver-requires-darwin-host.c @@ -0,0 +1,13 @@ +// REQUIRES: system-darwin + +// RUN: env XROS_DEPLOYMENT_TARGET=1.0 %clang -arch arm64 -c -### %s 2>&1 | FileCheck %s + +// RUN: rm -rf %t.dir +// RUN: mkdir -p %t.dir/XROS1.0.sdk +// RUN: %clang -arch arm64 -isysroot %t.dir/XROS1.0.sdk -c -### %s 2>&1 | FileCheck %s +// RUN: mkdir -p %t.dir/XRSimulator1.0.sdk +// RUN: %clang -arch arm64 -isysroot %t.dir/XRSimulator1.0.sdk -c -### %s 2>&1 | FileCheck --check-prefix=CHECK_SIM %s + + +// CHECK: "-cc1"{{.*}} "-triple" "arm64-apple-xros1.0.0" +// CHECK_SIM: "-cc1"{{.*}} "-triple" "arm64-apple-xros1.0.0-simulator" diff --git a/clang/test/Format/dump-config-objc-stdin.m b/clang/test/Format/dump-config-objc-stdin.m index b22ff7b3328caa51e65999b8b52c4bc70ec39af5..d81711a84d79bf40569d77698e59ea656584e844 100644 --- a/clang/test/Format/dump-config-objc-stdin.m +++ b/clang/test/Format/dump-config-objc-stdin.m @@ -1,5 +1,8 @@ +// RUN: clang-format -assume-filename=foo.m -dump-config | FileCheck %s + // RUN: clang-format -dump-config - < %s | FileCheck %s // CHECK: Language: ObjC + @interface Foo @end diff --git a/clang/test/Format/verbose.cpp b/clang/test/Format/verbose.cpp index dd625e3f67e55d5fc4ccb607777ef2e47a78ab9f..4ab03d8f62aefc971a8285eb6a6f51df23bdb98c 100644 --- a/clang/test/Format/verbose.cpp +++ b/clang/test/Format/verbose.cpp @@ -1,12 +1,6 @@ -// RUN: clang-format %s 2> %t.stderr +// RUN: clang-format -verbose 2> %t.stderr // RUN: not grep "Formatting" %t.stderr -// RUN: clang-format %s -verbose 2> %t.stderr -// RUN: grep -E "Formatting (.*)verbose.cpp(.*)" %t.stderr -// RUN: clang-format %s -verbose=false 2> %t.stderr -// RUN: not grep "Formatting" %t.stderr - -int a; -// RUN: clang-format %s 2> %t.stderr +// RUN: clang-format %s 2> %t.stderr // RUN: not grep "Formatting" %t.stderr // RUN: clang-format %s -verbose 2> %t.stderr // RUN: grep -E "Formatting (.*)verbose.cpp(.*)" %t.stderr diff --git a/clang/test/Frontend/embed-bitcode.ll b/clang/test/Frontend/embed-bitcode.ll index defb2d12f2f0bae3186b7e6de2aed988ce39fdd0..9b8632d04dd985c78447662f87d062e1b606fb5a 100644 --- a/clang/test/Frontend/embed-bitcode.ll +++ b/clang/test/Frontend/embed-bitcode.ll @@ -7,7 +7,7 @@ ; RUN: %clang_cc1 -triple thumbv7-apple-ios8.0.0 -emit-llvm \ ; RUN: -fembed-bitcode=marker -x ir %s -o - \ ; RUN: | FileCheck %s -check-prefix=CHECK-MARKER -; RUN: %clang_cc1 -triple aarch64-unknown-linux-gnueabi -emit-llvm \ +; RUN: %clang_cc1 -triple aarch64 -emit-llvm \ ; RUN: -fembed-bitcode=all -x ir %s -o - \ ; RUN: | FileCheck %s -check-prefix=CHECK-ELF diff --git a/clang/test/Frontend/gnu-mcount.c b/clang/test/Frontend/gnu-mcount.c index e54983ca356ad6598299aa10e29d07147056d98f..a6ee4b274593e745f4c25f82b185dfdf1757c537 100644 --- a/clang/test/Frontend/gnu-mcount.c +++ b/clang/test/Frontend/gnu-mcount.c @@ -2,36 +2,29 @@ // RUN: %clang -target armv7-unknown-none-eabi -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,UNSUPPORTED // RUN: %clang -target armv7-unknown-none-eabi -pg -meabi gnu -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNSUPPORTED -// RUN: %clang -target aarch64-unknown-none-gnu -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,MCOUNT -// RUN: %clang -target aarch64-unknown-none-gnu -pg -meabi gnu -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNDER +// RUN: %clang --target=aarch64-unknown-none-gnu -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,MCOUNT // RUN: %clang -target armv7-unknown-linux-gnueabi -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-ARM-EABI // RUN: %clang -target armv7-unknown-linux-gnueabi -meabi gnu -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-ARM-EABI-MEABI-GNU -// RUN: %clang -target aarch64-unknown-linux-gnueabi -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNDER -// RUN: %clang -target aarch64-unknown-linux-gnueabi -meabi gnu -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNDER +// RUN: %clang --target=aarch64-unknown-linux -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNDER // RUN: %clang -target armv7-unknown-linux-gnueabihf -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-ARM-EABI // RUN: %clang -target armv7-unknown-linux-gnueabihf -meabi gnu -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-ARM-EABI-MEABI-GNU -// RUN: %clang -target aarch64-unknown-linux-gnueabihf -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNDER -// RUN: %clang -target aarch64-unknown-linux-gnueabihf -meabi gnu -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNDER // RUN: %clang -target armv7-unknown-freebsd-gnueabihf -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNDER_UNDER // RUN: %clang -target armv7-unknown-freebsd-gnueabihf -meabi gnu -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNDER_UNDER -// RUN: %clang -target aarch64-unknown-freebsd-gnueabihf -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-ARM64-EABI-FREEBSD -// RUN: %clang -target aarch64-unknown-freebsd-gnueabihf -meabi gnu -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-ARM64-EABI-FREEBSD +// RUN: %clang --target=aarch64-unknown-freebsd -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-ARM64-EABI-FREEBSD // RUN: %clang -target armv7-unknown-openbsd-gnueabihf -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix UNDER_UNDER // RUN: %clang -target armv7-unknown-openbsd-gnueabihf -meabi gnu -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix UNDER_UNDER -// RUN: %clang -target aarch64-unknown-openbsd-gnueabihf -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix UNDER_UNDER -// RUN: %clang -target aarch64-unknown-openbsd-gnueabihf -meabi gnu -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNDER_UNDER +// RUN: %clang --target=aarch64-unknown-openbsd -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix UNDER_UNDER // RUN: %clang -target armv7-unknown-netbsd-gnueabihf -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNDER_UNDER // RUN: %clang -target armv7-unknown-netbsd-gnueabihf -meabi gnu -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNDER_UNDER -// RUN: %clang -target aarch64-unknown-netbsd-gnueabihf -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNDER_UNDER -// RUN: %clang -target aarch64-unknown-netbsd-gnueabihf -meabi gnu -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNDER_UNDER +// RUN: %clang --target=aarch64-unknown-netbsd -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNDER_UNDER // RUN: %clang -target armv7-apple-ios -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNSUPPORTED // RUN: %clang -target armv7-apple-ios -pg -meabi gnu -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNSUPPORTED // RUN: %clang -target arm64-apple-ios -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNSUPPORTED // RUN: %clang -target arm64-apple-ios -pg -meabi gnu -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,UNSUPPORTED // RUN: %clang -target armv7-unknown-rtems-gnueabihf -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,MCOUNT // RUN: %clang -target armv7-unknown-rtems-gnueabihf -meabi gnu -pg -S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,MCOUNT -// RUN: %clang -target aarch64-unknown-rtems-gnueabihf -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,MCOUNT -// RUN: %clang -target aarch64-unknown-rtems-gnueabihf -meabi gnu -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,MCOUNT +// RUN: %clang --target=aarch64-unknown-rtems -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,MCOUNT +// RUN: %clang --target=aarch64-unknown-rtems -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,MCOUNT int f() { return 0; diff --git a/clang/test/Headers/__clang_hip_cmath.hip b/clang/test/Headers/__clang_hip_cmath.hip index c194f4437890d07e88beffcd191767a11286f05b..cd085fdb5039a6117443359a123a8b157a203e6e 100644 --- a/clang/test/Headers/__clang_hip_cmath.hip +++ b/clang/test/Headers/__clang_hip_cmath.hip @@ -61,13 +61,13 @@ extern "C" __device__ float test_fabs_f32(float x) { // DEFAULT-LABEL: @test_sin_f32( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_sin_f32(float noundef [[X:%.*]]) #[[ATTR8:[0-9]+]] -// DEFAULT-NEXT: ret float [[CALL_I_I]] +// DEFAULT-NEXT: [[CALL_I1:%.*]] = tail call contract noundef float @__ocml_sin_f32(float noundef [[X:%.*]]) #[[ATTR8:[0-9]+]] +// DEFAULT-NEXT: ret float [[CALL_I1]] // // FINITEONLY-LABEL: @test_sin_f32( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR8:[0-9]+]] -// FINITEONLY-NEXT: ret float [[CALL_I_I]] +// FINITEONLY-NEXT: [[CALL_I1:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR8:[0-9]+]] +// FINITEONLY-NEXT: ret float [[CALL_I1]] // extern "C" __device__ float test_sin_f32(float x) { return sin(x); @@ -75,13 +75,13 @@ extern "C" __device__ float test_sin_f32(float x) { // DEFAULT-LABEL: @test_cos_f32( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_cos_f32(float noundef [[X:%.*]]) #[[ATTR8]] -// DEFAULT-NEXT: ret float [[CALL_I_I]] +// DEFAULT-NEXT: [[CALL_I1:%.*]] = tail call contract noundef float @__ocml_cos_f32(float noundef [[X:%.*]]) #[[ATTR8]] +// DEFAULT-NEXT: ret float [[CALL_I1]] // // FINITEONLY-LABEL: @test_cos_f32( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR8]] -// FINITEONLY-NEXT: ret float [[CALL_I_I]] +// FINITEONLY-NEXT: [[CALL_I1:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR8]] +// FINITEONLY-NEXT: ret float [[CALL_I1]] // extern "C" __device__ float test_cos_f32(float x) { return cos(x); diff --git a/clang/test/Headers/__clang_hip_math.hip b/clang/test/Headers/__clang_hip_math.hip index 5230c360d0bef5c7e5a878dace2ff2b3b408181f..37099de74fb8ecf29d2bc69b9ee469573ee3c2ff 100644 --- a/clang/test/Headers/__clang_hip_math.hip +++ b/clang/test/Headers/__clang_hip_math.hip @@ -258,17 +258,17 @@ extern "C" __device__ long long test_llabs(long x) { // DEFAULT-LABEL: @test_acosf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_acos_f32(float noundef [[X:%.*]]) #[[ATTR14:[0-9]+]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_acos_f32(float noundef [[X:%.*]]) #[[ATTR12:[0-9]+]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_acosf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_acos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14:[0-9]+]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_acos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR12:[0-9]+]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_acosf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_acos_f32(float noundef [[X:%.*]]) #[[ATTR14:[0-9]+]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_acos_f32(float noundef [[X:%.*]]) #[[ATTR12:[0-9]+]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_acosf(float x) { @@ -277,17 +277,17 @@ extern "C" __device__ float test_acosf(float x) { // DEFAULT-LABEL: @test_acos( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_acos_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_acos_f64(double noundef [[X:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_acos( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_acos_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_acos_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_acos( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_acos_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_acos_f64(double noundef [[X:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_acos(double x) { @@ -296,17 +296,17 @@ extern "C" __device__ double test_acos(double x) { // DEFAULT-LABEL: @test_acoshf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_acosh_f32(float noundef [[X:%.*]]) #[[ATTR15:[0-9]+]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_acosh_f32(float noundef [[X:%.*]]) #[[ATTR13:[0-9]+]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_acoshf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_acosh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15:[0-9]+]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_acosh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13:[0-9]+]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_acoshf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_acosh_f32(float noundef [[X:%.*]]) #[[ATTR15:[0-9]+]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_acosh_f32(float noundef [[X:%.*]]) #[[ATTR13:[0-9]+]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_acoshf(float x) { @@ -315,17 +315,17 @@ extern "C" __device__ float test_acoshf(float x) { // DEFAULT-LABEL: @test_acosh( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_acosh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_acosh_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_acosh( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_acosh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_acosh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_acosh( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_acosh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_acosh_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_acosh(double x) { @@ -334,17 +334,17 @@ extern "C" __device__ double test_acosh(double x) { // DEFAULT-LABEL: @test_asinf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_asin_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_asin_f32(float noundef [[X:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_asinf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_asin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_asin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_asinf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_asin_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_asin_f32(float noundef [[X:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_asinf(float x) { @@ -353,17 +353,17 @@ extern "C" __device__ float test_asinf(float x) { // DEFAULT-LABEL: @test_asin( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_asin_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_asin_f64(double noundef [[X:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_asin( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_asin_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_asin_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_asin( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_asin_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_asin_f64(double noundef [[X:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_asin(double x) { @@ -373,17 +373,17 @@ extern "C" __device__ double test_asin(double x) { // DEFAULT-LABEL: @test_asinhf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_asinh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_asinh_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_asinhf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_asinh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_asinh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_asinhf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_asinh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_asinh_f32(float noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_asinhf(float x) { @@ -392,17 +392,17 @@ extern "C" __device__ float test_asinhf(float x) { // DEFAULT-LABEL: @test_asinh( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_asinh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_asinh_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_asinh( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_asinh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_asinh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_asinh( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_asinh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_asinh_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_asinh(double x) { @@ -411,17 +411,17 @@ extern "C" __device__ double test_asinh(double x) { // DEFAULT-LABEL: @test_atan2f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atan2_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atan2_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_atan2f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_atan2_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_atan2_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_atan2f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atan2_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atan2_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_atan2f(float x, float y) { @@ -430,17 +430,17 @@ extern "C" __device__ float test_atan2f(float x, float y) { // DEFAULT-LABEL: @test_atan2( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atan2_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atan2_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_atan2( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_atan2_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_atan2_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_atan2( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atan2_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atan2_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_atan2(double x, double y) { @@ -449,17 +449,17 @@ extern "C" __device__ double test_atan2(double x, double y) { // DEFAULT-LABEL: @test_atanf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atan_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atan_f32(float noundef [[X:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_atanf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_atan_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_atan_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_atanf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atan_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atan_f32(float noundef [[X:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_atanf(float x) { @@ -468,17 +468,17 @@ extern "C" __device__ float test_atanf(float x) { // DEFAULT-LABEL: @test_atan( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atan_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atan_f64(double noundef [[X:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_atan( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_atan_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_atan_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_atan( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atan_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atan_f64(double noundef [[X:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_atan(double x) { @@ -487,17 +487,17 @@ extern "C" __device__ double test_atan(double x) { // DEFAULT-LABEL: @test_atanhf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atanh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atanh_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_atanhf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_atanh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_atanh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_atanhf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atanh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atanh_f32(float noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_atanhf(float x) { @@ -506,17 +506,17 @@ extern "C" __device__ float test_atanhf(float x) { // DEFAULT-LABEL: @test_atanh( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atanh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atanh_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_atanh( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_atanh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_atanh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_atanh( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atanh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atanh_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_atanh(double x) { @@ -525,17 +525,17 @@ extern "C" __device__ double test_atanh(double x) { // DEFAULT-LABEL: @test_cbrtf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cbrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cbrt_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_cbrtf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cbrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cbrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_cbrtf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cbrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cbrt_f32(float noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_cbrtf(float x) { @@ -544,17 +544,17 @@ extern "C" __device__ float test_cbrtf(float x) { // DEFAULT-LABEL: @test_cbrt( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cbrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cbrt_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_cbrt( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_cbrt_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_cbrt_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_cbrt( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cbrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cbrt_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_cbrt(double x) { @@ -639,17 +639,17 @@ extern "C" __device__ double test_copysign(double x, double y) { // DEFAULT-LABEL: @test_cosf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cos_f32(float noundef [[X:%.*]]) #[[ATTR16:[0-9]+]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cos_f32(float noundef [[X:%.*]]) #[[ATTR14:[0-9]+]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_cosf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16:[0-9]+]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14:[0-9]+]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_cosf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I1:%.*]] = tail call contract noundef float @__ocml_native_cos_f32(float noundef [[X:%.*]]) #[[ATTR16:[0-9]+]] +// APPROX-NEXT: [[CALL_I1:%.*]] = tail call contract noundef float @__ocml_native_cos_f32(float noundef [[X:%.*]]) #[[ATTR14:[0-9]+]] // APPROX-NEXT: ret float [[CALL_I1]] // extern "C" __device__ float test_cosf(float x) { @@ -658,17 +658,17 @@ extern "C" __device__ float test_cosf(float x) { // DEFAULT-LABEL: @test_cos( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cos_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cos_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_cos( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_cos_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_cos_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_cos( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cos_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cos_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_cos(double x) { @@ -677,17 +677,17 @@ extern "C" __device__ double test_cos(double x) { // DEFAULT-LABEL: @test_coshf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cosh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cosh_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_coshf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cosh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cosh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_coshf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cosh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cosh_f32(float noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_coshf(float x) { @@ -696,17 +696,17 @@ extern "C" __device__ float test_coshf(float x) { // DEFAULT-LABEL: @test_cosh( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cosh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cosh_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_cosh( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_cosh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_cosh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_cosh( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cosh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cosh_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_cosh(double x) { @@ -715,17 +715,17 @@ extern "C" __device__ double test_cosh(double x) { // DEFAULT-LABEL: @test_cospif( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cospi_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cospi_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_cospif( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cospi_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cospi_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_cospif( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cospi_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cospi_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_cospif(float x) { @@ -734,17 +734,17 @@ extern "C" __device__ float test_cospif(float x) { // DEFAULT-LABEL: @test_cospi( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cospi_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cospi_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_cospi( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_cospi_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_cospi_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_cospi( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cospi_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cospi_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_cospi(double x) { @@ -753,17 +753,17 @@ extern "C" __device__ double test_cospi(double x) { // DEFAULT-LABEL: @test_cyl_bessel_i0f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_i0_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_i0_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_cyl_bessel_i0f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_i0_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_i0_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_cyl_bessel_i0f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_i0_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_i0_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_cyl_bessel_i0f(float x) { @@ -772,17 +772,17 @@ extern "C" __device__ float test_cyl_bessel_i0f(float x) { // DEFAULT-LABEL: @test_cyl_bessel_i0( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_i0_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_i0_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_cyl_bessel_i0( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_i0_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_i0_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_cyl_bessel_i0( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_i0_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_i0_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_cyl_bessel_i0(double x) { @@ -791,17 +791,17 @@ extern "C" __device__ double test_cyl_bessel_i0(double x) { // DEFAULT-LABEL: @test_cyl_bessel_i1f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_i1_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_i1_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_cyl_bessel_i1f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_i1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_i1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_cyl_bessel_i1f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_i1_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_i1_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_cyl_bessel_i1f(float x) { @@ -810,17 +810,17 @@ extern "C" __device__ float test_cyl_bessel_i1f(float x) { // DEFAULT-LABEL: @test_cyl_bessel_i1( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_i1_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_i1_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_cyl_bessel_i1( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_i1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_i1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_cyl_bessel_i1( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_i1_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_i1_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_cyl_bessel_i1(double x) { @@ -829,17 +829,17 @@ extern "C" __device__ double test_cyl_bessel_i1(double x) { // DEFAULT-LABEL: @test_erfcf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_erfc_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_erfc_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_erfcf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_erfc_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_erfc_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_erfcf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_erfc_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_erfc_f32(float noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_erfcf(float x) { @@ -848,17 +848,17 @@ extern "C" __device__ float test_erfcf(float x) { // DEFAULT-LABEL: @test_erfc( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_erfc_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_erfc_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_erfc( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_erfc_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_erfc_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_erfc( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_erfc_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_erfc_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_erfc(double x) { @@ -867,17 +867,17 @@ extern "C" __device__ double test_erfc(double x) { // DEFAULT-LABEL: @test_erfinvf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_erfinv_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_erfinv_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_erfinvf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_erfinv_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_erfinv_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_erfinvf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_erfinv_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_erfinv_f32(float noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_erfinvf(float x) { @@ -886,17 +886,17 @@ extern "C" __device__ float test_erfinvf(float x) { // DEFAULT-LABEL: @test_erfinv( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_erfinv_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_erfinv_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_erfinv( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_erfinv_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_erfinv_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_erfinv( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_erfinv_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_erfinv_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_erfinv(double x) { @@ -905,17 +905,17 @@ extern "C" __device__ double test_erfinv(double x) { // DEFAULT-LABEL: @test_exp10f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_exp10_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_exp10_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_exp10f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_exp10_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_exp10_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_exp10f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_exp10_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_exp10_f32(float noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_exp10f(float x) { @@ -924,17 +924,17 @@ extern "C" __device__ float test_exp10f(float x) { // DEFAULT-LABEL: @test_exp10( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp10_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp10_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_exp10( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_exp10_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_exp10_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_exp10( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp10_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp10_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_exp10(double x) { @@ -962,17 +962,17 @@ extern "C" __device__ float test_exp2f(float x) { // DEFAULT-LABEL: @test_exp2( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp2_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp2_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_exp2( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_exp2_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_exp2_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_exp2( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp2_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp2_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_exp2(double x) { @@ -1000,17 +1000,17 @@ extern "C" __device__ float test_expf(float x) { // DEFAULT-LABEL: @test_exp( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_exp( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_exp_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_exp_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_exp( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_exp(double x) { @@ -1019,17 +1019,17 @@ extern "C" __device__ double test_exp(double x) { // DEFAULT-LABEL: @test_expm1f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_expm1_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_expm1_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_expm1f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_expm1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_expm1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_expm1f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_expm1_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_expm1_f32(float noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_expm1f(float x) { @@ -1038,17 +1038,17 @@ extern "C" __device__ float test_expm1f(float x) { // DEFAULT-LABEL: @test_expm1( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_expm1_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_expm1_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_expm1( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_expm1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_expm1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_expm1( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_expm1_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_expm1_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_expm1(double x) { @@ -1095,17 +1095,17 @@ extern "C" __device__ double test_fabs(double x) { // DEFAULT-LABEL: @test_fdimf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fdim_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fdim_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_fdimf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_fdim_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_fdim_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_fdimf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fdim_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fdim_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_fdimf(float x, float y) { @@ -1114,17 +1114,17 @@ extern "C" __device__ float test_fdimf(float x, float y) { // DEFAULT-LABEL: @test_fdim( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fdim_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fdim_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_fdim( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_fdim_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_fdim_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_fdim( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fdim_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fdim_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_fdim(double x, double y) { @@ -1323,17 +1323,17 @@ extern "C" __device__ double test_fmin(double x, double y) { // DEFAULT-LABEL: @test_fmodf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fmod_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fmod_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_fmodf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_fmod_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_fmod_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_fmodf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fmod_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fmod_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_fmodf(float x, float y) { @@ -1342,17 +1342,17 @@ extern "C" __device__ float test_fmodf(float x, float y) { // DEFAULT-LABEL: @test_fmod( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fmod_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fmod_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_fmod( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_fmod_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_fmod_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_fmod( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fmod_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fmod_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_fmod(double x, double y) { @@ -1385,17 +1385,17 @@ extern "C" __device__ double test_frexp(double x, int* y) { // DEFAULT-LABEL: @test_hypotf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_hypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_hypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_hypotf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_hypot_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_hypot_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_hypotf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_hypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_hypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_hypotf(float x, float y) { @@ -1404,17 +1404,17 @@ extern "C" __device__ float test_hypotf(float x, float y) { // DEFAULT-LABEL: @test_hypot( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_hypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_hypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_hypot( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_hypot_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_hypot_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_hypot( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_hypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_hypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_hypot(double x, double y) { @@ -1423,17 +1423,17 @@ extern "C" __device__ double test_hypot(double x, double y) { // DEFAULT-LABEL: @test_ilogbf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f32(float noundef [[X:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret i32 [[CALL_I]] // // FINITEONLY-LABEL: @test_ilogbf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret i32 [[CALL_I]] // // APPROX-LABEL: @test_ilogbf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f32(float noundef [[X:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret i32 [[CALL_I]] // extern "C" __device__ int test_ilogbf(float x) { @@ -1442,17 +1442,17 @@ extern "C" __device__ int test_ilogbf(float x) { // DEFAULT-LABEL: @test_ilogb( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f64(double noundef [[X:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret i32 [[CALL_I]] // // FINITEONLY-LABEL: @test_ilogb( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret i32 [[CALL_I]] // // APPROX-LABEL: @test_ilogb( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f64(double noundef [[X:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret i32 [[CALL_I]] // extern "C" __device__ int test_ilogb(double x) { @@ -1589,17 +1589,17 @@ extern "C" __device__ BOOL_TYPE test___isnan(double x) { // DEFAULT-LABEL: @test_j0f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_j0f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j0_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j0_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_j0f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_j0f(float x) { @@ -1608,17 +1608,17 @@ extern "C" __device__ float test_j0f(float x) { // DEFAULT-LABEL: @test_j0( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_j0( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j0_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j0_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_j0( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_j0(double x) { @@ -1627,17 +1627,17 @@ extern "C" __device__ double test_j0(double x) { // DEFAULT-LABEL: @test_j1f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_j1f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_j1f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_j1f(float x) { @@ -1646,17 +1646,17 @@ extern "C" __device__ float test_j1f(float x) { // DEFAULT-LABEL: @test_j1( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_j1( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_j1( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_j1(double x) { @@ -1670,14 +1670,14 @@ extern "C" __device__ double test_j1(double x) { // DEFAULT-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // DEFAULT-NEXT: ] // DEFAULT: if.then.i: -// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[Y:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: br label [[_ZL3JNFIF_EXIT:%.*]] // DEFAULT: if.then2.i: -// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR14]] // DEFAULT-NEXT: br label [[_ZL3JNFIF_EXIT]] // DEFAULT: if.end4.i: -// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[Y]]) #[[ATTR16]] -// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[Y]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR14]] // DEFAULT-NEXT: [[CMP7_I1:%.*]] = icmp sgt i32 [[X]], 1 // DEFAULT-NEXT: br i1 [[CMP7_I1]], label [[FOR_BODY_I:%.*]], label [[_ZL3JNFIF_EXIT]] // DEFAULT: for.body.i: @@ -1703,14 +1703,14 @@ extern "C" __device__ double test_j1(double x) { // FINITEONLY-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // FINITEONLY-NEXT: ] // FINITEONLY: if.then.i: -// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j0_f32(float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j0_f32(float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: br label [[_ZL3JNFIF_EXIT:%.*]] // FINITEONLY: if.then2.i: -// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR14]] // FINITEONLY-NEXT: br label [[_ZL3JNFIF_EXIT]] // FINITEONLY: if.end4.i: -// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j0_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] -// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j0_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR14]] // FINITEONLY-NEXT: [[CMP7_I1:%.*]] = icmp sgt i32 [[X]], 1 // FINITEONLY-NEXT: br i1 [[CMP7_I1]], label [[FOR_BODY_I:%.*]], label [[_ZL3JNFIF_EXIT]] // FINITEONLY: for.body.i: @@ -1736,14 +1736,14 @@ extern "C" __device__ double test_j1(double x) { // APPROX-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // APPROX-NEXT: ] // APPROX: if.then.i: -// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[Y:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: br label [[_ZL3JNFIF_EXIT:%.*]] // APPROX: if.then2.i: -// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR14]] // APPROX-NEXT: br label [[_ZL3JNFIF_EXIT]] // APPROX: if.end4.i: -// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[Y]]) #[[ATTR16]] -// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[Y]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR14]] // APPROX-NEXT: [[CMP7_I1:%.*]] = icmp sgt i32 [[X]], 1 // APPROX-NEXT: br i1 [[CMP7_I1]], label [[FOR_BODY_I:%.*]], label [[_ZL3JNFIF_EXIT]] // APPROX: for.body.i: @@ -1773,14 +1773,14 @@ extern "C" __device__ float test_jnf(int x, float y) { // DEFAULT-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // DEFAULT-NEXT: ] // DEFAULT: if.then.i: -// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[Y:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: br label [[_ZL2JNID_EXIT:%.*]] // DEFAULT: if.then2.i: -// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR14]] // DEFAULT-NEXT: br label [[_ZL2JNID_EXIT]] // DEFAULT: if.end4.i: -// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[Y]]) #[[ATTR16]] -// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[Y]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR14]] // DEFAULT-NEXT: [[CMP7_I1:%.*]] = icmp sgt i32 [[X]], 1 // DEFAULT-NEXT: br i1 [[CMP7_I1]], label [[FOR_BODY_I:%.*]], label [[_ZL2JNID_EXIT]] // DEFAULT: for.body.i: @@ -1806,14 +1806,14 @@ extern "C" __device__ float test_jnf(int x, float y) { // FINITEONLY-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // FINITEONLY-NEXT: ] // FINITEONLY: if.then.i: -// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j0_f64(double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j0_f64(double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: br label [[_ZL2JNID_EXIT:%.*]] // FINITEONLY: if.then2.i: -// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR14]] // FINITEONLY-NEXT: br label [[_ZL2JNID_EXIT]] // FINITEONLY: if.end4.i: -// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j0_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] -// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j0_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR14]] // FINITEONLY-NEXT: [[CMP7_I1:%.*]] = icmp sgt i32 [[X]], 1 // FINITEONLY-NEXT: br i1 [[CMP7_I1]], label [[FOR_BODY_I:%.*]], label [[_ZL2JNID_EXIT]] // FINITEONLY: for.body.i: @@ -1839,14 +1839,14 @@ extern "C" __device__ float test_jnf(int x, float y) { // APPROX-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // APPROX-NEXT: ] // APPROX: if.then.i: -// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[Y:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: br label [[_ZL2JNID_EXIT:%.*]] // APPROX: if.then2.i: -// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR14]] // APPROX-NEXT: br label [[_ZL2JNID_EXIT]] // APPROX: if.end4.i: -// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[Y]]) #[[ATTR16]] -// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[Y]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR14]] // APPROX-NEXT: [[CMP7_I1:%.*]] = icmp sgt i32 [[X]], 1 // APPROX-NEXT: br i1 [[CMP7_I1]], label [[FOR_BODY_I:%.*]], label [[_ZL2JNID_EXIT]] // APPROX: for.body.i: @@ -1909,17 +1909,17 @@ extern "C" __device__ double test_ldexp(double x, int y) { // DEFAULT-LABEL: @test_lgammaf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_lgamma_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_lgamma_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_lgammaf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_lgamma_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_lgamma_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_lgammaf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_lgamma_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_lgamma_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_lgammaf(float x) { @@ -1928,17 +1928,17 @@ extern "C" __device__ float test_lgammaf(float x) { // DEFAULT-LABEL: @test_lgamma( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_lgamma_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_lgamma_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_lgamma( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_lgamma_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_lgamma_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_lgamma( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_lgamma_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_lgamma_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_lgamma(double x) { @@ -2054,17 +2054,17 @@ extern "C" __device__ float test_log10f(float x) { // DEFAULT-LABEL: @test_log10( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log10_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log10_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_log10( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_log10_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_log10_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_log10( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log10_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log10_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_log10(double x) { @@ -2073,17 +2073,17 @@ extern "C" __device__ double test_log10(double x) { // DEFAULT-LABEL: @test_log1pf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_log1p_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_log1p_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_log1pf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_log1p_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_log1p_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_log1pf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_log1p_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_log1p_f32(float noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_log1pf(float x) { @@ -2092,17 +2092,17 @@ extern "C" __device__ float test_log1pf(float x) { // DEFAULT-LABEL: @test_log1p( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log1p_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log1p_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_log1p( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_log1p_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_log1p_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_log1p( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log1p_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log1p_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_log1p(double x) { @@ -2111,12 +2111,12 @@ extern "C" __device__ double test_log1p(double x) { // DEFAULT-LABEL: @test_log2f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_log2_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_log2_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_log2f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_log2_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_log2_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_log2f( @@ -2130,17 +2130,17 @@ extern "C" __device__ float test_log2f(float x) { // DEFAULT-LABEL: @test_log2( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log2_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log2_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_log2( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_log2_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_log2_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_log2( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log2_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log2_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_log2(double x) { @@ -2149,17 +2149,17 @@ extern "C" __device__ double test_log2(double x) { // DEFAULT-LABEL: @test_logbf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_logb_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_logb_f32(float noundef [[X:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_logbf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_logb_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_logb_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_logbf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_logb_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_logb_f32(float noundef [[X:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_logbf(float x) { @@ -2168,17 +2168,17 @@ extern "C" __device__ float test_logbf(float x) { // DEFAULT-LABEL: @test_logb( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_logb_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_logb_f64(double noundef [[X:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_logb( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_logb_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_logb_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_logb( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_logb_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_logb_f64(double noundef [[X:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_logb(double x) { @@ -2187,12 +2187,12 @@ extern "C" __device__ double test_logb(double x) { // DEFAULT-LABEL: @test_logf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_log_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_log_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_logf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_log_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_log_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_logf( @@ -2295,31 +2295,31 @@ extern "C" __device__ long int test_lround(double x) { // DEFAULT-LABEL: @test_modff( // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[__TMP_I:%.*]] = alloca float, align 4, addrspace(5) -// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17:[0-9]+]] -// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract noundef float @__ocml_modf_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15:[0-9]+]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract noundef float @__ocml_modf_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // DEFAULT-NEXT: [[TMP0:%.*]] = load float, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA16:![0-9]+]] // DEFAULT-NEXT: store float [[TMP0]], ptr [[Y:%.*]], align 4, !tbaa [[TBAA16]] -// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_modff( // FINITEONLY-NEXT: entry: // FINITEONLY-NEXT: [[__TMP_I:%.*]] = alloca float, align 4, addrspace(5) -// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17:[0-9]+]] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_modf_f32(float noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15:[0-9]+]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_modf_f32(float noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // FINITEONLY-NEXT: [[TMP0:%.*]] = load float, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA16:![0-9]+]] // FINITEONLY-NEXT: store float [[TMP0]], ptr [[Y:%.*]], align 4, !tbaa [[TBAA16]] -// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_modff( // APPROX-NEXT: entry: // APPROX-NEXT: [[__TMP_I:%.*]] = alloca float, align 4, addrspace(5) -// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17:[0-9]+]] -// APPROX-NEXT: [[CALL_I:%.*]] = call contract noundef float @__ocml_modf_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15:[0-9]+]] +// APPROX-NEXT: [[CALL_I:%.*]] = call contract noundef float @__ocml_modf_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // APPROX-NEXT: [[TMP0:%.*]] = load float, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA16:![0-9]+]] // APPROX-NEXT: store float [[TMP0]], ptr [[Y:%.*]], align 4, !tbaa [[TBAA16]] -// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_modff(float x, float* y) { @@ -2329,31 +2329,31 @@ extern "C" __device__ float test_modff(float x, float* y) { // DEFAULT-LABEL: @test_modf( // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[__TMP_I:%.*]] = alloca double, align 8, addrspace(5) -// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract noundef double @__ocml_modf_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract noundef double @__ocml_modf_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // DEFAULT-NEXT: [[TMP0:%.*]] = load double, ptr addrspace(5) [[__TMP_I]], align 8, !tbaa [[TBAA18:![0-9]+]] // DEFAULT-NEXT: store double [[TMP0]], ptr [[Y:%.*]], align 8, !tbaa [[TBAA18]] -// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_modf( // FINITEONLY-NEXT: entry: // FINITEONLY-NEXT: [[__TMP_I:%.*]] = alloca double, align 8, addrspace(5) -// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_modf_f64(double noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_modf_f64(double noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // FINITEONLY-NEXT: [[TMP0:%.*]] = load double, ptr addrspace(5) [[__TMP_I]], align 8, !tbaa [[TBAA18:![0-9]+]] // FINITEONLY-NEXT: store double [[TMP0]], ptr [[Y:%.*]], align 8, !tbaa [[TBAA18]] -// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_modf( // APPROX-NEXT: entry: // APPROX-NEXT: [[__TMP_I:%.*]] = alloca double, align 8, addrspace(5) -// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// APPROX-NEXT: [[CALL_I:%.*]] = call contract noundef double @__ocml_modf_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = call contract noundef double @__ocml_modf_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // APPROX-NEXT: [[TMP0:%.*]] = load double, ptr addrspace(5) [[__TMP_I]], align 8, !tbaa [[TBAA18:![0-9]+]] // APPROX-NEXT: store double [[TMP0]], ptr [[Y:%.*]], align 8, !tbaa [[TBAA18]] -// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_modf(double x, double* y) { @@ -2557,33 +2557,65 @@ extern "C" __device__ double test_nan(const char *tag) { return nan(tag); } -// CHECK-LABEL: @test_nanf_emptystr( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret float 0x7FF8000000000000 +// DEFAULT-LABEL: @test_nanf_emptystr( +// DEFAULT-NEXT: entry: +// DEFAULT-NEXT: ret float 0x7FF8000000000000 +// +// FINITEONLY-LABEL: @test_nanf_emptystr( +// FINITEONLY-NEXT: entry: +// FINITEONLY-NEXT: ret float poison +// +// APPROX-LABEL: @test_nanf_emptystr( +// APPROX-NEXT: entry: +// APPROX-NEXT: ret float 0x7FF8000000000000 // extern "C" __device__ float test_nanf_emptystr() { return nanf(""); } -// CHECK-LABEL: @test_nan_emptystr( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret double 0x7FF8000000000000 +// DEFAULT-LABEL: @test_nan_emptystr( +// DEFAULT-NEXT: entry: +// DEFAULT-NEXT: ret double 0x7FF8000000000000 +// +// FINITEONLY-LABEL: @test_nan_emptystr( +// FINITEONLY-NEXT: entry: +// FINITEONLY-NEXT: ret double poison +// +// APPROX-LABEL: @test_nan_emptystr( +// APPROX-NEXT: entry: +// APPROX-NEXT: ret double 0x7FF8000000000000 // extern "C" __device__ double test_nan_emptystr() { return nan(""); } -// CHECK-LABEL: @test_nanf_fill( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret float 0x7FF8000000000000 +// DEFAULT-LABEL: @test_nanf_fill( +// DEFAULT-NEXT: entry: +// DEFAULT-NEXT: ret float 0x7FF8000000000000 +// +// FINITEONLY-LABEL: @test_nanf_fill( +// FINITEONLY-NEXT: entry: +// FINITEONLY-NEXT: ret float poison +// +// APPROX-LABEL: @test_nanf_fill( +// APPROX-NEXT: entry: +// APPROX-NEXT: ret float 0x7FF8000000000000 // extern "C" __device__ float test_nanf_fill() { return nanf("0x456"); } -// CHECK-LABEL: @test_nan_fill( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret double 0x7FF8000000000000 +// DEFAULT-LABEL: @test_nan_fill( +// DEFAULT-NEXT: entry: +// DEFAULT-NEXT: ret double 0x7FF8000000000000 +// +// FINITEONLY-LABEL: @test_nan_fill( +// FINITEONLY-NEXT: entry: +// FINITEONLY-NEXT: ret double poison +// +// APPROX-LABEL: @test_nan_fill( +// APPROX-NEXT: entry: +// APPROX-NEXT: ret double 0x7FF8000000000000 // extern "C" __device__ double test_nan_fill() { return nan("0x123"); @@ -2629,17 +2661,17 @@ extern "C" __device__ double test_nearbyint(double x) { // DEFAULT-LABEL: @test_nextafterf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_nextafter_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_nextafter_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_nextafterf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_nextafter_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_nextafter_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_nextafterf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_nextafter_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_nextafter_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_nextafterf(float x, float y) { @@ -2648,17 +2680,17 @@ extern "C" __device__ float test_nextafterf(float x, float y) { // DEFAULT-LABEL: @test_nextafter( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_nextafter_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_nextafter_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_nextafter( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_nextafter_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_nextafter_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_nextafter( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_nextafter_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_nextafter_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_nextafter(double x, double y) { @@ -2667,17 +2699,17 @@ extern "C" __device__ double test_nextafter(double x, double y) { // DEFAULT-LABEL: @test_norm3df( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_len3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_len3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_norm3df( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_len3_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_len3_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_norm3df( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_len3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_len3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_norm3df(float x, float y, float z) { @@ -2686,17 +2718,17 @@ extern "C" __device__ float test_norm3df(float x, float y, float z) { // DEFAULT-LABEL: @test_norm3d( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_len3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_len3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_norm3d( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_len3_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_len3_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_norm3d( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_len3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_len3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_norm3d(double x, double y, double z) { @@ -2705,17 +2737,17 @@ extern "C" __device__ double test_norm3d(double x, double y, double z) { // DEFAULT-LABEL: @test_norm4df( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_len4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_len4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_norm4df( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_len4_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]], float noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_len4_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]], float noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_norm4df( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_len4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_len4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_norm4df(float x, float y, float z, float w) { @@ -2724,17 +2756,17 @@ extern "C" __device__ float test_norm4df(float x, float y, float z, float w) { // DEFAULT-LABEL: @test_norm4d( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_len4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_len4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_norm4d( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_len4_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]], double noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_len4_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]], double noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_norm4d( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_len4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_len4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_norm4d(double x, double y, double z, double w) { @@ -2743,17 +2775,17 @@ extern "C" __device__ double test_norm4d(double x, double y, double z, double w) // DEFAULT-LABEL: @test_normcdff( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_ncdf_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_ncdf_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_normcdff( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_ncdf_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_ncdf_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_normcdff( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_ncdf_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_ncdf_f32(float noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_normcdff(float x) { @@ -2762,17 +2794,17 @@ extern "C" __device__ float test_normcdff(float x) { // DEFAULT-LABEL: @test_normcdf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_ncdf_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_ncdf_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_normcdf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_ncdf_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_ncdf_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_normcdf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_ncdf_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_ncdf_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_normcdf(double x) { @@ -2781,17 +2813,17 @@ extern "C" __device__ double test_normcdf(double x) { // DEFAULT-LABEL: @test_normcdfinvf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_ncdfinv_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_ncdfinv_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_normcdfinvf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_ncdfinv_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_ncdfinv_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_normcdfinvf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_ncdfinv_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_ncdfinv_f32(float noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_normcdfinvf(float x) { @@ -2800,17 +2832,17 @@ extern "C" __device__ float test_normcdfinvf(float x) { // DEFAULT-LABEL: @test_normcdfinv( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_ncdfinv_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_ncdfinv_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_normcdfinv( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_ncdfinv_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_ncdfinv_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_normcdfinv( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_ncdfinv_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_ncdfinv_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_normcdfinv(double x) { @@ -2947,17 +2979,17 @@ extern "C" __device__ double test_norm(int x, const double *y) { // DEFAULT-LABEL: @test_powf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_powf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_pow_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_pow_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_powf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_powf(float x, float y) { @@ -2966,17 +2998,17 @@ extern "C" __device__ float test_powf(float x, float y) { // DEFAULT-LABEL: @test_pow( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_pow_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_pow_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_pow( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_pow_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_pow_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_pow( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_pow_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_pow_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_pow(double x, double y) { @@ -2985,17 +3017,17 @@ extern "C" __device__ double test_pow(double x, double y) { // DEFAULT-LABEL: @test_powif( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pown_f32(float noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pown_f32(float noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_powif( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_pown_f32(float noundef nofpclass(nan inf) [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_pown_f32(float noundef nofpclass(nan inf) [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_powif( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pown_f32(float noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pown_f32(float noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_powif(float x, int y) { @@ -3004,17 +3036,17 @@ extern "C" __device__ float test_powif(float x, int y) { // DEFAULT-LABEL: @test_powi( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_pown_f64(double noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_pown_f64(double noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_powi( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_pown_f64(double noundef nofpclass(nan inf) [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_pown_f64(double noundef nofpclass(nan inf) [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_powi( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_pown_f64(double noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_pown_f64(double noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_powi(double x, int y) { @@ -3023,17 +3055,17 @@ extern "C" __device__ double test_powi(double x, int y) { // DEFAULT-LABEL: @test_rcbrtf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rcbrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rcbrt_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_rcbrtf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rcbrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rcbrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_rcbrtf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rcbrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rcbrt_f32(float noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_rcbrtf(float x) { @@ -3042,17 +3074,17 @@ extern "C" __device__ float test_rcbrtf(float x) { // DEFAULT-LABEL: @test_rcbrt( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rcbrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rcbrt_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_rcbrt( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rcbrt_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rcbrt_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_rcbrt( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rcbrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rcbrt_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_rcbrt(double x) { @@ -3061,17 +3093,17 @@ extern "C" __device__ double test_rcbrt(double x) { // DEFAULT-LABEL: @test_remainderf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_remainder_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_remainder_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_remainderf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_remainder_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_remainder_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_remainderf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_remainder_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_remainder_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_remainderf(float x, float y) { @@ -3080,17 +3112,17 @@ extern "C" __device__ float test_remainderf(float x, float y) { // DEFAULT-LABEL: @test_remainder( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_remainder_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_remainder_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_remainder( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_remainder_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_remainder_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_remainder( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_remainder_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_remainder_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_remainder(double x, double y) { @@ -3100,31 +3132,31 @@ extern "C" __device__ double test_remainder(double x, double y) { // DEFAULT-LABEL: @test_remquof( // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[__TMP_I:%.*]] = alloca i32, align 4, addrspace(5) -// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract noundef float @__ocml_remquo_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract noundef float @__ocml_remquo_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // DEFAULT-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA12]] // DEFAULT-NEXT: store i32 [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA12]] -// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_remquof( // FINITEONLY-NEXT: entry: // FINITEONLY-NEXT: [[__TMP_I:%.*]] = alloca i32, align 4, addrspace(5) -// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_remquo_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_remquo_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // FINITEONLY-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA12]] // FINITEONLY-NEXT: store i32 [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA12]] -// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_remquof( // APPROX-NEXT: entry: // APPROX-NEXT: [[__TMP_I:%.*]] = alloca i32, align 4, addrspace(5) -// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// APPROX-NEXT: [[CALL_I:%.*]] = call contract noundef float @__ocml_remquo_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = call contract noundef float @__ocml_remquo_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // APPROX-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA12]] // APPROX-NEXT: store i32 [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA12]] -// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_remquof(float x, float y, int* z) { @@ -3134,31 +3166,31 @@ extern "C" __device__ float test_remquof(float x, float y, int* z) { // DEFAULT-LABEL: @test_remquo( // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[__TMP_I:%.*]] = alloca i32, align 4, addrspace(5) -// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract noundef double @__ocml_remquo_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract noundef double @__ocml_remquo_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // DEFAULT-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA12]] // DEFAULT-NEXT: store i32 [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA12]] -// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_remquo( // FINITEONLY-NEXT: entry: // FINITEONLY-NEXT: [[__TMP_I:%.*]] = alloca i32, align 4, addrspace(5) -// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_remquo_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_remquo_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // FINITEONLY-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA12]] // FINITEONLY-NEXT: store i32 [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA12]] -// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_remquo( // APPROX-NEXT: entry: // APPROX-NEXT: [[__TMP_I:%.*]] = alloca i32, align 4, addrspace(5) -// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// APPROX-NEXT: [[CALL_I:%.*]] = call contract noundef double @__ocml_remquo_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = call contract noundef double @__ocml_remquo_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // APPROX-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA12]] // APPROX-NEXT: store i32 [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA12]] -// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_remquo(double x, double y, int* z) { @@ -3167,17 +3199,17 @@ extern "C" __device__ double test_remquo(double x, double y, int* z) { // DEFAULT-LABEL: @test_rhypotf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rhypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rhypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_rhypotf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rhypot_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rhypot_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_rhypotf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rhypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rhypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_rhypotf(float x, float y) { @@ -3186,17 +3218,17 @@ extern "C" __device__ float test_rhypotf(float x, float y) { // DEFAULT-LABEL: @test_rhypot( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rhypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rhypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_rhypot( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rhypot_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rhypot_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_rhypot( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rhypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rhypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_rhypot(double x, double y) { @@ -3258,7 +3290,7 @@ extern "C" __device__ double test_rint(double x) { // DEFAULT-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL6RNORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP22:![0-9]+]] // DEFAULT: _ZL6rnormfiPKf.exit: // DEFAULT-NEXT: [[__R_0_I_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rsqrt_f32(float noundef [[__R_0_I_LCSSA]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rsqrt_f32(float noundef [[__R_0_I_LCSSA]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_rnormf( @@ -3278,7 +3310,7 @@ extern "C" __device__ double test_rint(double x) { // FINITEONLY-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL6RNORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP22:![0-9]+]] // FINITEONLY: _ZL6rnormfiPKf.exit: // FINITEONLY-NEXT: [[__R_0_I_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rsqrt_f32(float noundef nofpclass(nan inf) [[__R_0_I_LCSSA]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rsqrt_f32(float noundef nofpclass(nan inf) [[__R_0_I_LCSSA]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_rnormf( @@ -3298,7 +3330,7 @@ extern "C" __device__ double test_rint(double x) { // APPROX-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL6RNORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP22:![0-9]+]] // APPROX: _ZL6rnormfiPKf.exit: // APPROX-NEXT: [[__R_0_I_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rsqrt_f32(float noundef [[__R_0_I_LCSSA]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rsqrt_f32(float noundef [[__R_0_I_LCSSA]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_rnormf(int x, const float* y) { @@ -3322,7 +3354,7 @@ extern "C" __device__ float test_rnormf(int x, const float* y) { // DEFAULT-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5RNORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP23:![0-9]+]] // DEFAULT: _ZL5rnormiPKd.exit: // DEFAULT-NEXT: [[__R_0_I_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rsqrt_f64(double noundef [[__R_0_I_LCSSA]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rsqrt_f64(double noundef [[__R_0_I_LCSSA]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_rnorm( @@ -3342,7 +3374,7 @@ extern "C" __device__ float test_rnormf(int x, const float* y) { // FINITEONLY-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5RNORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP23:![0-9]+]] // FINITEONLY: _ZL5rnormiPKd.exit: // FINITEONLY-NEXT: [[__R_0_I_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rsqrt_f64(double noundef nofpclass(nan inf) [[__R_0_I_LCSSA]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rsqrt_f64(double noundef nofpclass(nan inf) [[__R_0_I_LCSSA]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_rnorm( @@ -3362,7 +3394,7 @@ extern "C" __device__ float test_rnormf(int x, const float* y) { // APPROX-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5RNORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP23:![0-9]+]] // APPROX: _ZL5rnormiPKd.exit: // APPROX-NEXT: [[__R_0_I_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rsqrt_f64(double noundef [[__R_0_I_LCSSA]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rsqrt_f64(double noundef [[__R_0_I_LCSSA]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_rnorm(int x, const double* y) { @@ -3371,17 +3403,17 @@ extern "C" __device__ double test_rnorm(int x, const double* y) { // DEFAULT-LABEL: @test_rnorm3df( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rlen3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rlen3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_rnorm3df( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rlen3_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rlen3_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_rnorm3df( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rlen3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rlen3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_rnorm3df(float x, float y, float z) { @@ -3390,17 +3422,17 @@ extern "C" __device__ float test_rnorm3df(float x, float y, float z) { // DEFAULT-LABEL: @test_rnorm3d( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rlen3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rlen3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_rnorm3d( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rlen3_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rlen3_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_rnorm3d( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rlen3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rlen3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_rnorm3d(double x, double y, double z) { @@ -3409,17 +3441,17 @@ extern "C" __device__ double test_rnorm3d(double x, double y, double z) { // DEFAULT-LABEL: @test_rnorm4df( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rlen4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rlen4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_rnorm4df( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rlen4_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]], float noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rlen4_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]], float noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_rnorm4df( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rlen4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rlen4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_rnorm4df(float x, float y, float z, float w) { @@ -3428,17 +3460,17 @@ extern "C" __device__ float test_rnorm4df(float x, float y, float z, float w) { // DEFAULT-LABEL: @test_rnorm4d( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rlen4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rlen4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_rnorm4d( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rlen4_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]], double noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rlen4_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]], double noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_rnorm4d( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rlen4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rlen4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_rnorm4d(double x, double y, double z, double w) { @@ -3485,17 +3517,17 @@ extern "C" __device__ double test_round(double x) { // DEFAULT-LABEL: @test_rsqrtf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rsqrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rsqrt_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_rsqrtf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rsqrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rsqrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_rsqrtf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rsqrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rsqrt_f32(float noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_rsqrtf(float x) { @@ -3504,17 +3536,17 @@ extern "C" __device__ float test_rsqrtf(float x) { // DEFAULT-LABEL: @test_rsqrt( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rsqrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rsqrt_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_rsqrt( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rsqrt_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rsqrt_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_rsqrt( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rsqrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rsqrt_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_rsqrt(double x) { @@ -3530,7 +3562,7 @@ extern "C" __device__ double test_rsqrt(double x) { // DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[CONV_I]]) // DEFAULT-NEXT: br label [[_ZL8SCALBLNFFL_EXIT:%.*]] // DEFAULT: cond.false.i: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_scalb_f32(float noundef [[X]], float noundef 0x43E0000000000000) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_scalb_f32(float noundef [[X]], float noundef 0x43E0000000000000) #[[ATTR12]] // DEFAULT-NEXT: br label [[_ZL8SCALBLNFFL_EXIT]] // DEFAULT: _ZL8scalblnffl.exit: // DEFAULT-NEXT: [[COND_I:%.*]] = phi contract float [ [[TMP0]], [[COND_TRUE_I]] ], [ [[CALL_I]], [[COND_FALSE_I]] ] @@ -3545,7 +3577,7 @@ extern "C" __device__ double test_rsqrt(double x) { // FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[CONV_I]]) // FINITEONLY-NEXT: br label [[_ZL8SCALBLNFFL_EXIT:%.*]] // FINITEONLY: cond.false.i: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_scalb_f32(float noundef nofpclass(nan inf) [[X]], float noundef nofpclass(nan inf) 0x43E0000000000000) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_scalb_f32(float noundef nofpclass(nan inf) [[X]], float noundef nofpclass(nan inf) 0x43E0000000000000) #[[ATTR12]] // FINITEONLY-NEXT: br label [[_ZL8SCALBLNFFL_EXIT]] // FINITEONLY: _ZL8scalblnffl.exit: // FINITEONLY-NEXT: [[COND_I:%.*]] = phi nnan ninf contract float [ [[TMP0]], [[COND_TRUE_I]] ], [ [[CALL_I]], [[COND_FALSE_I]] ] @@ -3560,7 +3592,7 @@ extern "C" __device__ double test_rsqrt(double x) { // APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[CONV_I]]) // APPROX-NEXT: br label [[_ZL8SCALBLNFFL_EXIT:%.*]] // APPROX: cond.false.i: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_scalb_f32(float noundef [[X]], float noundef 0x43E0000000000000) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_scalb_f32(float noundef [[X]], float noundef 0x43E0000000000000) #[[ATTR12]] // APPROX-NEXT: br label [[_ZL8SCALBLNFFL_EXIT]] // APPROX: _ZL8scalblnffl.exit: // APPROX-NEXT: [[COND_I:%.*]] = phi contract float [ [[TMP0]], [[COND_TRUE_I]] ], [ [[CALL_I]], [[COND_FALSE_I]] ] @@ -3579,7 +3611,7 @@ extern "C" __device__ float test_scalblnf(float x, long int y) { // DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.ldexp.f64.i32(double [[X:%.*]], i32 [[CONV_I]]) // DEFAULT-NEXT: br label [[_ZL7SCALBLNDL_EXIT:%.*]] // DEFAULT: cond.false.i: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_scalb_f64(double noundef [[X]], double noundef 0x43E0000000000000) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_scalb_f64(double noundef [[X]], double noundef 0x43E0000000000000) #[[ATTR12]] // DEFAULT-NEXT: br label [[_ZL7SCALBLNDL_EXIT]] // DEFAULT: _ZL7scalblndl.exit: // DEFAULT-NEXT: [[COND_I:%.*]] = phi contract double [ [[TMP0]], [[COND_TRUE_I]] ], [ [[CALL_I]], [[COND_FALSE_I]] ] @@ -3594,7 +3626,7 @@ extern "C" __device__ float test_scalblnf(float x, long int y) { // FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.ldexp.f64.i32(double [[X:%.*]], i32 [[CONV_I]]) // FINITEONLY-NEXT: br label [[_ZL7SCALBLNDL_EXIT:%.*]] // FINITEONLY: cond.false.i: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_scalb_f64(double noundef nofpclass(nan inf) [[X]], double noundef nofpclass(nan inf) 0x43E0000000000000) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_scalb_f64(double noundef nofpclass(nan inf) [[X]], double noundef nofpclass(nan inf) 0x43E0000000000000) #[[ATTR12]] // FINITEONLY-NEXT: br label [[_ZL7SCALBLNDL_EXIT]] // FINITEONLY: _ZL7scalblndl.exit: // FINITEONLY-NEXT: [[COND_I:%.*]] = phi nnan ninf contract double [ [[TMP0]], [[COND_TRUE_I]] ], [ [[CALL_I]], [[COND_FALSE_I]] ] @@ -3609,7 +3641,7 @@ extern "C" __device__ float test_scalblnf(float x, long int y) { // APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.ldexp.f64.i32(double [[X:%.*]], i32 [[CONV_I]]) // APPROX-NEXT: br label [[_ZL7SCALBLNDL_EXIT:%.*]] // APPROX: cond.false.i: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_scalb_f64(double noundef [[X]], double noundef 0x43E0000000000000) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_scalb_f64(double noundef [[X]], double noundef 0x43E0000000000000) #[[ATTR12]] // APPROX-NEXT: br label [[_ZL7SCALBLNDL_EXIT]] // APPROX: _ZL7scalblndl.exit: // APPROX-NEXT: [[COND_I:%.*]] = phi contract double [ [[TMP0]], [[COND_TRUE_I]] ], [ [[CALL_I]], [[COND_FALSE_I]] ] @@ -3681,34 +3713,34 @@ extern "C" __device__ BOOL_TYPE test___signbit(double x) { // DEFAULT-LABEL: @test_sincosf( // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[__TMP_I:%.*]] = alloca float, align 4, addrspace(5) -// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract float @__ocml_sincos_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract float @__ocml_sincos_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // DEFAULT-NEXT: store float [[CALL_I]], ptr [[Y:%.*]], align 4, !tbaa [[TBAA16]] // DEFAULT-NEXT: [[TMP0:%.*]] = load float, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA16]] // DEFAULT-NEXT: store float [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA16]] -// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // DEFAULT-NEXT: ret void // // FINITEONLY-LABEL: @test_sincosf( // FINITEONLY-NEXT: entry: // FINITEONLY-NEXT: [[__TMP_I:%.*]] = alloca float, align 4, addrspace(5) -// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract nofpclass(nan inf) float @__ocml_sincos_f32(float noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract nofpclass(nan inf) float @__ocml_sincos_f32(float noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // FINITEONLY-NEXT: store float [[CALL_I]], ptr [[Y:%.*]], align 4, !tbaa [[TBAA16]] // FINITEONLY-NEXT: [[TMP0:%.*]] = load float, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA16]] // FINITEONLY-NEXT: store float [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA16]] -// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // FINITEONLY-NEXT: ret void // // APPROX-LABEL: @test_sincosf( // APPROX-NEXT: entry: // APPROX-NEXT: [[__TMP_I:%.*]] = alloca float, align 4, addrspace(5) -// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// APPROX-NEXT: [[CALL_I:%.*]] = call contract float @__ocml_sincos_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = call contract float @__ocml_sincos_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // APPROX-NEXT: store float [[CALL_I]], ptr [[Y:%.*]], align 4, !tbaa [[TBAA16]] // APPROX-NEXT: [[TMP0:%.*]] = load float, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA16]] // APPROX-NEXT: store float [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA16]] -// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // APPROX-NEXT: ret void // extern "C" __device__ void test_sincosf(float x, float *y, float *z) { @@ -3718,34 +3750,34 @@ extern "C" __device__ void test_sincosf(float x, float *y, float *z) { // DEFAULT-LABEL: @test_sincos( // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[__TMP_I:%.*]] = alloca double, align 8, addrspace(5) -// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract double @__ocml_sincos_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract double @__ocml_sincos_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // DEFAULT-NEXT: store double [[CALL_I]], ptr [[Y:%.*]], align 8, !tbaa [[TBAA18]] // DEFAULT-NEXT: [[TMP0:%.*]] = load double, ptr addrspace(5) [[__TMP_I]], align 8, !tbaa [[TBAA18]] // DEFAULT-NEXT: store double [[TMP0]], ptr [[Z:%.*]], align 8, !tbaa [[TBAA18]] -// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // DEFAULT-NEXT: ret void // // FINITEONLY-LABEL: @test_sincos( // FINITEONLY-NEXT: entry: // FINITEONLY-NEXT: [[__TMP_I:%.*]] = alloca double, align 8, addrspace(5) -// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract nofpclass(nan inf) double @__ocml_sincos_f64(double noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract nofpclass(nan inf) double @__ocml_sincos_f64(double noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // FINITEONLY-NEXT: store double [[CALL_I]], ptr [[Y:%.*]], align 8, !tbaa [[TBAA18]] // FINITEONLY-NEXT: [[TMP0:%.*]] = load double, ptr addrspace(5) [[__TMP_I]], align 8, !tbaa [[TBAA18]] // FINITEONLY-NEXT: store double [[TMP0]], ptr [[Z:%.*]], align 8, !tbaa [[TBAA18]] -// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // FINITEONLY-NEXT: ret void // // APPROX-LABEL: @test_sincos( // APPROX-NEXT: entry: // APPROX-NEXT: [[__TMP_I:%.*]] = alloca double, align 8, addrspace(5) -// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// APPROX-NEXT: [[CALL_I:%.*]] = call contract double @__ocml_sincos_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = call contract double @__ocml_sincos_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // APPROX-NEXT: store double [[CALL_I]], ptr [[Y:%.*]], align 8, !tbaa [[TBAA18]] // APPROX-NEXT: [[TMP0:%.*]] = load double, ptr addrspace(5) [[__TMP_I]], align 8, !tbaa [[TBAA18]] // APPROX-NEXT: store double [[TMP0]], ptr [[Z:%.*]], align 8, !tbaa [[TBAA18]] -// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // APPROX-NEXT: ret void // extern "C" __device__ void test_sincos(double x, double *y, double *z) { @@ -3755,34 +3787,34 @@ extern "C" __device__ void test_sincos(double x, double *y, double *z) { // DEFAULT-LABEL: @test_sincospif( // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[__TMP_I:%.*]] = alloca float, align 4, addrspace(5) -// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract float @__ocml_sincospi_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract float @__ocml_sincospi_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // DEFAULT-NEXT: store float [[CALL_I]], ptr [[Y:%.*]], align 4, !tbaa [[TBAA16]] // DEFAULT-NEXT: [[TMP0:%.*]] = load float, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA16]] // DEFAULT-NEXT: store float [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA16]] -// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // DEFAULT-NEXT: ret void // // FINITEONLY-LABEL: @test_sincospif( // FINITEONLY-NEXT: entry: // FINITEONLY-NEXT: [[__TMP_I:%.*]] = alloca float, align 4, addrspace(5) -// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract nofpclass(nan inf) float @__ocml_sincospi_f32(float noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract nofpclass(nan inf) float @__ocml_sincospi_f32(float noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // FINITEONLY-NEXT: store float [[CALL_I]], ptr [[Y:%.*]], align 4, !tbaa [[TBAA16]] // FINITEONLY-NEXT: [[TMP0:%.*]] = load float, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA16]] // FINITEONLY-NEXT: store float [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA16]] -// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // FINITEONLY-NEXT: ret void // // APPROX-LABEL: @test_sincospif( // APPROX-NEXT: entry: // APPROX-NEXT: [[__TMP_I:%.*]] = alloca float, align 4, addrspace(5) -// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// APPROX-NEXT: [[CALL_I:%.*]] = call contract float @__ocml_sincospi_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = call contract float @__ocml_sincospi_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // APPROX-NEXT: store float [[CALL_I]], ptr [[Y:%.*]], align 4, !tbaa [[TBAA16]] // APPROX-NEXT: [[TMP0:%.*]] = load float, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA16]] // APPROX-NEXT: store float [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA16]] -// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // APPROX-NEXT: ret void // extern "C" __device__ void test_sincospif(float x, float *y, float *z) { @@ -3792,34 +3824,34 @@ extern "C" __device__ void test_sincospif(float x, float *y, float *z) { // DEFAULT-LABEL: @test_sincospi( // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[__TMP_I:%.*]] = alloca double, align 8, addrspace(5) -// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract double @__ocml_sincospi_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract double @__ocml_sincospi_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // DEFAULT-NEXT: store double [[CALL_I]], ptr [[Y:%.*]], align 8, !tbaa [[TBAA18]] // DEFAULT-NEXT: [[TMP0:%.*]] = load double, ptr addrspace(5) [[__TMP_I]], align 8, !tbaa [[TBAA18]] // DEFAULT-NEXT: store double [[TMP0]], ptr [[Z:%.*]], align 8, !tbaa [[TBAA18]] -// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // DEFAULT-NEXT: ret void // // FINITEONLY-LABEL: @test_sincospi( // FINITEONLY-NEXT: entry: // FINITEONLY-NEXT: [[__TMP_I:%.*]] = alloca double, align 8, addrspace(5) -// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract nofpclass(nan inf) double @__ocml_sincospi_f64(double noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract nofpclass(nan inf) double @__ocml_sincospi_f64(double noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // FINITEONLY-NEXT: store double [[CALL_I]], ptr [[Y:%.*]], align 8, !tbaa [[TBAA18]] // FINITEONLY-NEXT: [[TMP0:%.*]] = load double, ptr addrspace(5) [[__TMP_I]], align 8, !tbaa [[TBAA18]] // FINITEONLY-NEXT: store double [[TMP0]], ptr [[Z:%.*]], align 8, !tbaa [[TBAA18]] -// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // FINITEONLY-NEXT: ret void // // APPROX-LABEL: @test_sincospi( // APPROX-NEXT: entry: // APPROX-NEXT: [[__TMP_I:%.*]] = alloca double, align 8, addrspace(5) -// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// APPROX-NEXT: [[CALL_I:%.*]] = call contract double @__ocml_sincospi_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = call contract double @__ocml_sincospi_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR14]] // APPROX-NEXT: store double [[CALL_I]], ptr [[Y:%.*]], align 8, !tbaa [[TBAA18]] // APPROX-NEXT: [[TMP0:%.*]] = load double, ptr addrspace(5) [[__TMP_I]], align 8, !tbaa [[TBAA18]] // APPROX-NEXT: store double [[TMP0]], ptr [[Z:%.*]], align 8, !tbaa [[TBAA18]] -// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] +// APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR15]] // APPROX-NEXT: ret void // extern "C" __device__ void test_sincospi(double x, double *y, double *z) { @@ -3828,17 +3860,17 @@ extern "C" __device__ void test_sincospi(double x, double *y, double *z) { // DEFAULT-LABEL: @test_sinf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sin_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_sinf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_sinf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I1:%.*]] = tail call contract noundef float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I1:%.*]] = tail call contract noundef float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I1]] // extern "C" __device__ float test_sinf(float x) { @@ -3847,17 +3879,17 @@ extern "C" __device__ float test_sinf(float x) { // DEFAULT-LABEL: @test_sin( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sin_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sin_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_sin( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_sin_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_sin_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_sin( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sin_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sin_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_sin(double x) { @@ -3866,17 +3898,17 @@ extern "C" __device__ double test_sin(double x) { // DEFAULT-LABEL: @test_sinpif( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sinpi_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sinpi_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_sinpif( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_sinpi_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_sinpi_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_sinpif( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sinpi_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sinpi_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_sinpif(float x) { @@ -3885,17 +3917,17 @@ extern "C" __device__ float test_sinpif(float x) { // DEFAULT-LABEL: @test_sinpi( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sinpi_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sinpi_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_sinpi( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_sinpi_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_sinpi_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_sinpi( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sinpi_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sinpi_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_sinpi(double x) { @@ -3942,17 +3974,17 @@ extern "C" __device__ double test_sqrt(double x) { // DEFAULT-LABEL: @test_tanf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tan_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tan_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_tanf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_tan_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_tan_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_tanf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tan_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tan_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_tanf(float x) { @@ -3961,17 +3993,17 @@ extern "C" __device__ float test_tanf(float x) { // DEFAULT-LABEL: @test_tan( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tan_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tan_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_tan( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_tan_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_tan_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_tan( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tan_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tan_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_tan(double x) { @@ -3980,17 +4012,17 @@ extern "C" __device__ double test_tan(double x) { // DEFAULT-LABEL: @test_tanhf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tanh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tanh_f32(float noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_tanhf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_tanh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_tanh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_tanhf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tanh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tanh_f32(float noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_tanhf(float x) { @@ -3999,17 +4031,17 @@ extern "C" __device__ float test_tanhf(float x) { // DEFAULT-LABEL: @test_tanh( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tanh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tanh_f64(double noundef [[X:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_tanh( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_tanh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_tanh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_tanh( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tanh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tanh_f64(double noundef [[X:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_tanh(double x) { @@ -4018,17 +4050,17 @@ extern "C" __device__ double test_tanh(double x) { // DEFAULT-LABEL: @test_tgammaf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tgamma_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tgamma_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_tgammaf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_tgamma_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_tgamma_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_tgammaf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tgamma_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tgamma_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_tgammaf(float x) { @@ -4037,17 +4069,17 @@ extern "C" __device__ float test_tgammaf(float x) { // DEFAULT-LABEL: @test_tgamma( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tgamma_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tgamma_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_tgamma( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_tgamma_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_tgamma_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_tgamma( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tgamma_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tgamma_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_tgamma(double x) { @@ -4094,17 +4126,17 @@ extern "C" __device__ double test_trunc(double x) { // DEFAULT-LABEL: @test_y0f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_y0f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y0_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y0_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_y0f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_y0f(float x) { @@ -4113,17 +4145,17 @@ extern "C" __device__ float test_y0f(float x) { // DEFAULT-LABEL: @test_y0( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_y0( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y0_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y0_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_y0( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_y0(double x) { @@ -4132,17 +4164,17 @@ extern "C" __device__ double test_y0(double x) { // DEFAULT-LABEL: @test_y1f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_y1f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_y1f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_y1f(float x) { @@ -4151,17 +4183,17 @@ extern "C" __device__ float test_y1f(float x) { // DEFAULT-LABEL: @test_y1( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_y1( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_y1( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_y1(double x) { @@ -4175,14 +4207,14 @@ extern "C" __device__ double test_y1(double x) { // DEFAULT-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // DEFAULT-NEXT: ] // DEFAULT: if.then.i: -// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[Y:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: br label [[_ZL3YNFIF_EXIT:%.*]] // DEFAULT: if.then2.i: -// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR14]] // DEFAULT-NEXT: br label [[_ZL3YNFIF_EXIT]] // DEFAULT: if.end4.i: -// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[Y]]) #[[ATTR16]] -// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[Y]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR14]] // DEFAULT-NEXT: [[CMP7_I1:%.*]] = icmp sgt i32 [[X]], 1 // DEFAULT-NEXT: br i1 [[CMP7_I1]], label [[FOR_BODY_I:%.*]], label [[_ZL3YNFIF_EXIT]] // DEFAULT: for.body.i: @@ -4208,14 +4240,14 @@ extern "C" __device__ double test_y1(double x) { // FINITEONLY-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // FINITEONLY-NEXT: ] // FINITEONLY: if.then.i: -// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y0_f32(float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y0_f32(float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: br label [[_ZL3YNFIF_EXIT:%.*]] // FINITEONLY: if.then2.i: -// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR14]] // FINITEONLY-NEXT: br label [[_ZL3YNFIF_EXIT]] // FINITEONLY: if.end4.i: -// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y0_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] -// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y0_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR14]] // FINITEONLY-NEXT: [[CMP7_I1:%.*]] = icmp sgt i32 [[X]], 1 // FINITEONLY-NEXT: br i1 [[CMP7_I1]], label [[FOR_BODY_I:%.*]], label [[_ZL3YNFIF_EXIT]] // FINITEONLY: for.body.i: @@ -4241,14 +4273,14 @@ extern "C" __device__ double test_y1(double x) { // APPROX-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // APPROX-NEXT: ] // APPROX: if.then.i: -// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[Y:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: br label [[_ZL3YNFIF_EXIT:%.*]] // APPROX: if.then2.i: -// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR14]] // APPROX-NEXT: br label [[_ZL3YNFIF_EXIT]] // APPROX: if.end4.i: -// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[Y]]) #[[ATTR16]] -// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[Y]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR14]] // APPROX-NEXT: [[CMP7_I1:%.*]] = icmp sgt i32 [[X]], 1 // APPROX-NEXT: br i1 [[CMP7_I1]], label [[FOR_BODY_I:%.*]], label [[_ZL3YNFIF_EXIT]] // APPROX: for.body.i: @@ -4278,14 +4310,14 @@ extern "C" __device__ float test_ynf(int x, float y) { // DEFAULT-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // DEFAULT-NEXT: ] // DEFAULT: if.then.i: -// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[Y:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: br label [[_ZL2YNID_EXIT:%.*]] // DEFAULT: if.then2.i: -// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR14]] // DEFAULT-NEXT: br label [[_ZL2YNID_EXIT]] // DEFAULT: if.end4.i: -// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[Y]]) #[[ATTR16]] -// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[Y]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR14]] // DEFAULT-NEXT: [[CMP7_I1:%.*]] = icmp sgt i32 [[X]], 1 // DEFAULT-NEXT: br i1 [[CMP7_I1]], label [[FOR_BODY_I:%.*]], label [[_ZL2YNID_EXIT]] // DEFAULT: for.body.i: @@ -4311,14 +4343,14 @@ extern "C" __device__ float test_ynf(int x, float y) { // FINITEONLY-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // FINITEONLY-NEXT: ] // FINITEONLY: if.then.i: -// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y0_f64(double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y0_f64(double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: br label [[_ZL2YNID_EXIT:%.*]] // FINITEONLY: if.then2.i: -// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR14]] // FINITEONLY-NEXT: br label [[_ZL2YNID_EXIT]] // FINITEONLY: if.end4.i: -// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y0_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] -// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y0_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR14]] // FINITEONLY-NEXT: [[CMP7_I1:%.*]] = icmp sgt i32 [[X]], 1 // FINITEONLY-NEXT: br i1 [[CMP7_I1]], label [[FOR_BODY_I:%.*]], label [[_ZL2YNID_EXIT]] // FINITEONLY: for.body.i: @@ -4344,14 +4376,14 @@ extern "C" __device__ float test_ynf(int x, float y) { // APPROX-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // APPROX-NEXT: ] // APPROX: if.then.i: -// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[Y:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: br label [[_ZL2YNID_EXIT:%.*]] // APPROX: if.then2.i: -// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR14]] // APPROX-NEXT: br label [[_ZL2YNID_EXIT]] // APPROX: if.end4.i: -// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[Y]]) #[[ATTR16]] -// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[Y]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR14]] // APPROX-NEXT: [[CMP7_I1:%.*]] = icmp sgt i32 [[X]], 1 // APPROX-NEXT: br i1 [[CMP7_I1]], label [[FOR_BODY_I:%.*]], label [[_ZL2YNID_EXIT]] // APPROX: for.body.i: @@ -4376,17 +4408,17 @@ extern "C" __device__ double test_yn(int x, double y) { // DEFAULT-LABEL: @test___cosf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_cos_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_cos_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test___cosf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_native_cos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_native_cos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test___cosf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_cos_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_cos_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___cosf(float x) { @@ -4553,17 +4585,17 @@ extern "C" __device__ float test___frsqrt_rn(float x) { // DEFAULT-LABEL: @test___fsqrt_rn( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_sqrt_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_sqrt_f32(float noundef [[X:%.*]]) #[[ATTR12]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test___fsqrt_rn( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_native_sqrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_native_sqrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR12]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test___fsqrt_rn( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_sqrt_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_sqrt_f32(float noundef [[X:%.*]]) #[[ATTR12]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fsqrt_rn(float x) { @@ -4648,17 +4680,17 @@ extern "C" __device__ float test___logf(float x) { // DEFAULT-LABEL: @test___powf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR13]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test___powf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_pow_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_pow_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR13]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test___powf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR13]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___powf(float x, float y) { @@ -4695,25 +4727,25 @@ extern "C" __device__ float test___saturatef(float x) { // DEFAULT-LABEL: @test___sincosf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: store float [[CALL_I]], ptr [[Y:%.*]], align 4, !tbaa [[TBAA16]] -// DEFAULT-NEXT: [[CALL1_I:%.*]] = tail call contract float @__ocml_native_cos_f32(float noundef [[X]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL1_I:%.*]] = tail call contract float @__ocml_native_cos_f32(float noundef [[X]]) #[[ATTR14]] // DEFAULT-NEXT: store float [[CALL1_I]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA16]] // DEFAULT-NEXT: ret void // // FINITEONLY-LABEL: @test___sincosf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_native_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_native_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: store float [[CALL_I]], ptr [[Y:%.*]], align 4, !tbaa [[TBAA16]] -// FINITEONLY-NEXT: [[CALL1_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_native_cos_f32(float noundef nofpclass(nan inf) [[X]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL1_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_native_cos_f32(float noundef nofpclass(nan inf) [[X]]) #[[ATTR14]] // FINITEONLY-NEXT: store float [[CALL1_I]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA16]] // FINITEONLY-NEXT: ret void // // APPROX-LABEL: @test___sincosf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: store float [[CALL_I]], ptr [[Y:%.*]], align 4, !tbaa [[TBAA16]] -// APPROX-NEXT: [[CALL1_I:%.*]] = tail call contract float @__ocml_native_cos_f32(float noundef [[X]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL1_I:%.*]] = tail call contract float @__ocml_native_cos_f32(float noundef [[X]]) #[[ATTR14]] // APPROX-NEXT: store float [[CALL1_I]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA16]] // APPROX-NEXT: ret void // @@ -4723,17 +4755,17 @@ extern "C" __device__ void test___sincosf(float x, float *y, float *z) { // DEFAULT-LABEL: @test___sinf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test___sinf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_native_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_native_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test___sinf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___sinf(float x) { @@ -4742,24 +4774,24 @@ extern "C" __device__ float test___sinf(float x) { // DEFAULT-LABEL: @test___tanf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I3_I:%.*]] = tail call contract noundef float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] -// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_native_cos_f32(float noundef [[X]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I3_I:%.*]] = tail call contract noundef float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_native_cos_f32(float noundef [[X]]) #[[ATTR14]] // DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.amdgcn.rcp.f32(float [[CALL_I_I]]) // DEFAULT-NEXT: [[MUL_I:%.*]] = fmul contract float [[CALL_I3_I]], [[TMP0]] // DEFAULT-NEXT: ret float [[MUL_I]] // // FINITEONLY-LABEL: @test___tanf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I3_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_native_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] -// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_native_cos_f32(float noundef nofpclass(nan inf) [[X]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I3_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_native_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_native_cos_f32(float noundef nofpclass(nan inf) [[X]]) #[[ATTR14]] // FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.amdgcn.rcp.f32(float [[CALL_I_I]]) // FINITEONLY-NEXT: [[MUL_I:%.*]] = fmul nnan ninf contract float [[CALL_I3_I]], [[TMP0]] // FINITEONLY-NEXT: ret float [[MUL_I]] // // APPROX-LABEL: @test___tanf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I3_I:%.*]] = tail call contract noundef float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] -// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_native_cos_f32(float noundef [[X]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I3_I:%.*]] = tail call contract noundef float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_native_cos_f32(float noundef [[X]]) #[[ATTR14]] // APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.amdgcn.rcp.f32(float [[CALL_I_I]]) // APPROX-NEXT: [[MUL_I:%.*]] = fmul contract float [[CALL_I3_I]], [[TMP0]] // APPROX-NEXT: ret float [[MUL_I]] diff --git a/clang/test/Headers/arm-acle-header.c b/clang/test/Headers/arm-acle-header.c index 1084a8cf87e19f46c0bb6a24b8698363333a4a97..f04c7e1f0f35f7e779ac69ef13c7a5512d19fbea 100644 --- a/clang/test/Headers/arm-acle-header.c +++ b/clang/test/Headers/arm-acle-header.c @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -triple armv7-eabi -target-cpu cortex-a15 -fsyntax-only -ffreestanding %s -// RUN: %clang_cc1 -triple aarch64-eabi -target-cpu cortex-a53 -fsyntax-only -ffreestanding %s +// RUN: %clang_cc1 -triple aarch64 -target-cpu cortex-a53 -fsyntax-only -ffreestanding %s // RUN: %clang_cc1 -triple thumbv7-windows -target-cpu cortex-a53 -fsyntax-only -ffreestanding %s // RUN: %clang_cc1 -x c++ -triple armv7-eabi -target-cpu cortex-a15 -fsyntax-only -ffreestanding %s -// RUN: %clang_cc1 -x c++ -triple aarch64-eabi -target-cpu cortex-a57 -fsyntax-only -ffreestanding %s +// RUN: %clang_cc1 -x c++ -triple aarch64 -target-cpu cortex-a57 -fsyntax-only -ffreestanding %s // RUN: %clang_cc1 -x c++ -triple thumbv7-windows -target-cpu cortex-a15 -fsyntax-only -ffreestanding %s // RUN: %clang_cc1 -x c++ -triple thumbv7-windows -target-cpu cortex-a15 -fsyntax-only -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=19.11 %s // RUN: %clang_cc1 -x c++ -triple aarch64-windows -target-cpu cortex-a53 -fsyntax-only -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=19.11 %s diff --git a/clang/test/Headers/xmmintrin-unsupported.c b/clang/test/Headers/xmmintrin-unsupported.c index 1991a132f451cd57e24302a9cf4ae2097b2a9de9..870be81ff29a711caac02ba52e6462505ddd5382 100644 --- a/clang/test/Headers/xmmintrin-unsupported.c +++ b/clang/test/Headers/xmmintrin-unsupported.c @@ -1,4 +1,4 @@ -// RUN: not %clang_cc1 %s -triple aarch64-eabi -fsyntax-only 2>&1 | FileCheck %s +// RUN: not %clang_cc1 %s -triple aarch64 -fsyntax-only 2>&1 | FileCheck %s // // REQUIRES: x86-registered-target // CHECK: This header is only meant to be used on x86 and x64 architecture diff --git a/clang/test/Misc/target-invalid-cpu-note.c b/clang/test/Misc/target-invalid-cpu-note.c index 2f10bfb1fd82fe349655fdab140b9a8d790e7816..123b203af3e9ca8cd768209e692b9d10993b63b1 100644 --- a/clang/test/Misc/target-invalid-cpu-note.c +++ b/clang/test/Misc/target-invalid-cpu-note.c @@ -5,11 +5,11 @@ // RUN: not %clang_cc1 -triple arm64--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix AARCH64 // AARCH64: error: unknown target CPU 'not-a-cpu' -// AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, cobalt-100, grace{{$}} +// AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}} // RUN: not %clang_cc1 -triple arm64--- -tune-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix TUNE_AARCH64 // TUNE_AARCH64: error: unknown target CPU 'not-a-cpu' -// TUNE_AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, cobalt-100, grace{{$}} +// TUNE_AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}} // RUN: not %clang_cc1 -triple i386--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix X86 // X86: error: unknown target CPU 'not-a-cpu' @@ -37,7 +37,7 @@ // RUN: not %clang_cc1 -triple amdgcn--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix AMDGCN // AMDGCN: error: unknown target CPU 'not-a-cpu' -// AMDGCN-NEXT: note: valid target CPU values are: gfx600, tahiti, gfx601, pitcairn, verde, gfx602, hainan, oland, gfx700, kaveri, gfx701, hawaii, gfx702, gfx703, kabini, mullins, gfx704, bonaire, gfx705, gfx801, carrizo, gfx802, iceland, tonga, gfx803, fiji, polaris10, polaris11, gfx805, tongapro, gfx810, stoney, gfx900, gfx902, gfx904, gfx906, gfx908, gfx909, gfx90a, gfx90c, gfx940, gfx941, gfx942, gfx1010, gfx1011, gfx1012, gfx1013, gfx1030, gfx1031, gfx1032, gfx1033, gfx1034, gfx1035, gfx1036, gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1200, gfx1201{{$}} +// AMDGCN-NEXT: note: valid target CPU values are: gfx600, tahiti, gfx601, pitcairn, verde, gfx602, hainan, oland, gfx700, kaveri, gfx701, hawaii, gfx702, gfx703, kabini, mullins, gfx704, bonaire, gfx705, gfx801, carrizo, gfx802, iceland, tonga, gfx803, fiji, polaris10, polaris11, gfx805, tongapro, gfx810, stoney, gfx900, gfx902, gfx904, gfx906, gfx908, gfx909, gfx90a, gfx90c, gfx940, gfx941, gfx942, gfx1010, gfx1011, gfx1012, gfx1013, gfx1030, gfx1031, gfx1032, gfx1033, gfx1034, gfx1035, gfx1036, gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1200, gfx1201, gfx9-generic, gfx10.1-generic, gfx10.3-generic, gfx11-generic{{$}} // RUN: not %clang_cc1 -triple wasm64--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix WEBASM // WEBASM: error: unknown target CPU 'not-a-cpu' diff --git a/clang/test/OpenMP/for_loop_auto.cpp b/clang/test/OpenMP/for_loop_auto.cpp index b2c5540a7785ab9437377a36faafb2aea33cd35c..4467de6bba18dce0bd0a89d5405dfb7f70de0342 100644 --- a/clang/test/OpenMP/for_loop_auto.cpp +++ b/clang/test/OpenMP/for_loop_auto.cpp @@ -10,7 +10,7 @@ #ifndef HEADER #define HEADER -// CHECK: template <> void do_loop(const auto &v) { +// CHECK: void do_loop(const auto &v) { // CHECK-NEXT: #pragma omp parallel for // CHECK-NEXT: for (const auto &i : v) // CHECK-NEXT: ; diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c index 41fb26e04ef69b4d1fa0db1550bc908369af26fc..6ec4dcd60cf6010104585525a7f2a1a2b1edda60 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -244,16 +244,16 @@ // On ARMv8.2-A and above, +fp16fml implies +fp16. // On ARMv8.4-A and above, +fp16 implies +fp16fml. -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2-a+nofp16fml+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2-a+nofp16+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2-a+fp16+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8-a+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8-a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+nofp16fml+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+nofp16+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+fp16+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.2-a+nofp16fml+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.2-a+nofp16+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.2-a+fp16+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8-a+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8-a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.4-a+nofp16fml+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.4-a+nofp16+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.4-a+fp16+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.4-a+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.4-a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s // CHECK-FULLFP16-FML: #define __ARM_FEATURE_FP16_FML 1 // CHECK-FULLFP16-NOFML-NOT: #define __ARM_FEATURE_FP16_FML 1 // CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1 @@ -263,24 +263,24 @@ // +fp16fml+nosimd doesn't make sense as the fp16fml instructions all require SIMD. // However, as +fp16fml implies +fp16 there is a set of defines that we would expect. -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8-a+fp16fml+nosimd -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8-a+fp16+nosimd -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+fp16fml+nosimd -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+fp16+nosimd -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8-a+fp16fml+nosimd -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8-a+fp16+nosimd -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.4-a+fp16fml+nosimd -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.4-a+fp16+nosimd -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s // CHECK-FULLFP16-SCALAR-NOT: #define __ARM_FEATURE_FP16_FML 1 // CHECK-FULLFP16-SCALAR: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1 // CHECK-FULLFP16-SCALAR-NOT: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1 // CHECK-FULLFP16-SCALAR: #define __ARM_FP 0xE // CHECK-FULLFP16-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1 -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2-a -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2-a+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2-a+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2-a+fp16fml+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s -// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+fp16fml+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.2-a -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.2-a+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.2-a+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.2-a+fp16fml+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.4-a -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.4-a+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.4-a+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s +// RUN: %clang --target=aarch64 -march=armv8.4-a+fp16fml+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s // CHECK-FULLFP16-NOFML-VECTOR-SCALAR-NOT: #define __ARM_FEATURE_FP16_FML 1 // CHECK-FULLFP16-NOFML-VECTOR-SCALAR-NOT: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1 // CHECK-FULLFP16-NOFML-VECTOR-SCALAR-NOT: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1 @@ -600,14 +600,14 @@ // CHECK-NOSYS128-NOT: __ARM_FEATURE_SYSREG128 1 // ================== Check Armv8.9-A/Armv9.4-A Guarded Control Stack (FEAT_GCS) -// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.9-a -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-NOGCS,CHECK-NOGCS-DEFAULT %s -// RUN: %clang -target aarch64-arm-none-eabi -march=armv9.4-a -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-NOGCS,CHECK-NOGCS-DEFAULT %s -// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.9-a+gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-GCS,CHECK-NOGCS-DEFAULT %s -// RUN: %clang -target aarch64-arm-none-eabi -march=armv9.4-a+gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-GCS,CHECK-NOGCS-DEFAULT %s -// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.9-a -mbranch-protection=gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-NOGCS,CHECK-GCS-DEFAULT %s -// RUN: %clang -target aarch64-arm-none-eabi -march=armv9.4-a -mbranch-protection=gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-NOGCS,CHECK-GCS-DEFAULT %s -// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.9-a+gcs -mbranch-protection=gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-GCS,CHECK-GCS-DEFAULT %s -// RUN: %clang -target aarch64-arm-none-eabi -march=armv9.4-a+gcs -mbranch-protection=gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-GCS,CHECK-GCS-DEFAULT %s +// RUN: %clang --target=aarch64 -march=armv8.9-a -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-NOGCS,CHECK-NOGCS-DEFAULT %s +// RUN: %clang --target=aarch64 -march=armv9.4-a -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-NOGCS,CHECK-NOGCS-DEFAULT %s +// RUN: %clang --target=aarch64 -march=armv8.9-a+gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-GCS,CHECK-NOGCS-DEFAULT %s +// RUN: %clang --target=aarch64 -march=armv9.4-a+gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-GCS,CHECK-NOGCS-DEFAULT %s +// RUN: %clang --target=aarch64 -march=armv8.9-a -mbranch-protection=gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-NOGCS,CHECK-GCS-DEFAULT %s +// RUN: %clang --target=aarch64 -march=armv9.4-a -mbranch-protection=gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-NOGCS,CHECK-GCS-DEFAULT %s +// RUN: %clang --target=aarch64 -march=armv8.9-a+gcs -mbranch-protection=gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-GCS,CHECK-GCS-DEFAULT %s +// RUN: %clang --target=aarch64 -march=armv9.4-a+gcs -mbranch-protection=gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-GCS,CHECK-GCS-DEFAULT %s // CHECK-GCS: __ARM_FEATURE_GCS 1 // CHECK-NOGCS-NOT: __ARM_FEATURE_GCS 1 // CHECK-GCS-DEFAULT: __ARM_FEATURE_GCS_DEFAULT 1 diff --git a/clang/test/Preprocessor/arm-target-features.c b/clang/test/Preprocessor/arm-target-features.c index 236c9f2479b70580b763d49641c80eef3e562e5a..733d068b09b1fea81ac6a0526ce988f9db05982b 100644 --- a/clang/test/Preprocessor/arm-target-features.c +++ b/clang/test/Preprocessor/arm-target-features.c @@ -737,7 +737,7 @@ // Test whether predefines are as expected when targeting cortex-m55 (softfp FP ABI as default). // RUN: %clang -target arm-eabi -mcpu=cortex-m55 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=M55 %s -// M55: #define __ARM_ARCH 8 +// M55: #define __ARM_ARCH 801 // M55: #define __ARM_ARCH_8_1M_MAIN__ 1 // M55: #define __ARM_ARCH_EXT_IDIV__ 1 // M55-NOT: __ARM_ARCH_ISA_ARM @@ -764,7 +764,7 @@ // KRAIT-ALLOW-FP-INSTR:#define __ARM_VFPV4__ 1 // RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V81M %s -// CHECK-V81M: #define __ARM_ARCH 8 +// CHECK-V81M: #define __ARM_ARCH 801 // CHECK-V81M: #define __ARM_ARCH_8_1M_MAIN__ 1 // CHECK-V81M: #define __ARM_ARCH_ISA_THUMB 2 // CHECK-V81M: #define __ARM_ARCH_PROFILE 'M' @@ -821,14 +821,14 @@ // CHECK-V8M-CDE-MASK2: #define __ARM_FEATURE_CDE_COPROC 0xff // RUN: %clang -target armv8.1a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V81A %s -// CHECK-V81A: #define __ARM_ARCH 8 +// CHECK-V81A: #define __ARM_ARCH 801 // CHECK-V81A: #define __ARM_ARCH_8_1A__ 1 // CHECK-V81A: #define __ARM_ARCH_PROFILE 'A' // CHECK-V81A: #define __ARM_FEATURE_QRDMX 1 // CHECK-V81A: #define __ARM_FP 0xe // RUN: %clang -target armv8.2a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V82A %s -// CHECK-V82A: #define __ARM_ARCH 8 +// CHECK-V82A: #define __ARM_ARCH 802 // CHECK-V82A: #define __ARM_ARCH_8_2A__ 1 // CHECK-V82A: #define __ARM_ARCH_PROFILE 'A' // CHECK-V82A: #define __ARM_FEATURE_QRDMX 1 @@ -838,67 +838,67 @@ // CHECK-DRIVERKIT-NOT: #define __ARM_PCS_VFP 1 // RUN: %clang -target armv8.3a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V83A %s -// CHECK-V83A: #define __ARM_ARCH 8 +// CHECK-V83A: #define __ARM_ARCH 803 // CHECK-V83A: #define __ARM_ARCH_8_3A__ 1 // CHECK-V83A: #define __ARM_ARCH_PROFILE 'A' // RUN: %clang -target armv8.4a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V84A %s -// CHECK-V84A: #define __ARM_ARCH 8 +// CHECK-V84A: #define __ARM_ARCH 804 // CHECK-V84A: #define __ARM_ARCH_8_4A__ 1 // CHECK-V84A: #define __ARM_ARCH_PROFILE 'A' // RUN: %clang -target armv8.5a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V85A %s -// CHECK-V85A: #define __ARM_ARCH 8 +// CHECK-V85A: #define __ARM_ARCH 805 // CHECK-V85A: #define __ARM_ARCH_8_5A__ 1 // CHECK-V85A: #define __ARM_ARCH_PROFILE 'A' // RUN: %clang -target armv8.6a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V86A %s -// CHECK-V86A: #define __ARM_ARCH 8 +// CHECK-V86A: #define __ARM_ARCH 806 // CHECK-V86A: #define __ARM_ARCH_8_6A__ 1 // CHECK-V86A: #define __ARM_ARCH_PROFILE 'A' // RUN: %clang -target armv8.7a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V87A %s -// CHECK-V87A: #define __ARM_ARCH 8 +// CHECK-V87A: #define __ARM_ARCH 807 // CHECK-V87A: #define __ARM_ARCH_8_7A__ 1 // CHECK-V87A: #define __ARM_ARCH_PROFILE 'A' // RUN: %clang -target armv8.8a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V88A %s -// CHECK-V88A: #define __ARM_ARCH 8 +// CHECK-V88A: #define __ARM_ARCH 808 // CHECK-V88A: #define __ARM_ARCH_8_8A__ 1 // CHECK-V88A: #define __ARM_ARCH_PROFILE 'A' // RUN: %clang -target armv8.9a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V89A %s -// CHECK-V89A: #define __ARM_ARCH 8 +// CHECK-V89A: #define __ARM_ARCH 809 // CHECK-V89A: #define __ARM_ARCH_8_9A__ 1 // CHECK-V89A: #define __ARM_ARCH_PROFILE 'A' // RUN: %clang -target armv9a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V9A %s -// CHECK-V9A: #define __ARM_ARCH 9 +// CHECK-V9A: #define __ARM_ARCH 900 // CHECK-V9A: #define __ARM_ARCH_9A__ 1 // CHECK-V9A: #define __ARM_ARCH_PROFILE 'A' // RUN: %clang -target armv9.1a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V91A %s -// CHECK-V91A: #define __ARM_ARCH 9 +// CHECK-V91A: #define __ARM_ARCH 901 // CHECK-V91A: #define __ARM_ARCH_9_1A__ 1 // CHECK-V91A: #define __ARM_ARCH_PROFILE 'A' // RUN: %clang -target armv9.2a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V92A %s -// CHECK-V92A: #define __ARM_ARCH 9 +// CHECK-V92A: #define __ARM_ARCH 902 // CHECK-V92A: #define __ARM_ARCH_9_2A__ 1 // CHECK-V92A: #define __ARM_ARCH_PROFILE 'A' // RUN: %clang -target armv9.3a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V93A %s -// CHECK-V93A: #define __ARM_ARCH 9 +// CHECK-V93A: #define __ARM_ARCH 903 // CHECK-V93A: #define __ARM_ARCH_9_3A__ 1 // CHECK-V93A: #define __ARM_ARCH_PROFILE 'A' // RUN: %clang -target armv9.4a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V94A %s -// CHECK-V94A: #define __ARM_ARCH 9 +// CHECK-V94A: #define __ARM_ARCH 904 // CHECK-V94A: #define __ARM_ARCH_9_4A__ 1 // CHECK-V94A: #define __ARM_ARCH_PROFILE 'A' // RUN: %clang -target armv9.5a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V95A %s -// CHECK-V95A: #define __ARM_ARCH 9 +// CHECK-V95A: #define __ARM_ARCH 905 // CHECK-V95A: #define __ARM_ARCH_9_5A__ 1 // CHECK-V95A: #define __ARM_ARCH_PROFILE 'A' diff --git a/clang/test/Sema/aarch64-sme-func-attrs.c b/clang/test/Sema/aarch64-sme-func-attrs.c index 2bf1886951f1f795ea84f71f7a4359a756e0274c..47dbeca206a94e67b02004f3dda2c6677aafb77a 100644 --- a/clang/test/Sema/aarch64-sme-func-attrs.c +++ b/clang/test/Sema/aarch64-sme-func-attrs.c @@ -454,3 +454,43 @@ void unimplemented_spill_fill_za(void (*share_zt0_only)(void) __arm_inout("zt0") // expected-note@+1 {{add '__arm_preserves("za")' to the callee if it preserves ZA}} share_zt0_only(); } + +// expected-cpp-error@+2 {{streaming function cannot be multi-versioned}} +// expected-error@+1 {{streaming function cannot be multi-versioned}} +__attribute__((target_version("sme2"))) +void cannot_work_version(void) __arm_streaming {} +// expected-cpp-error@+5 {{function declared 'void ()' was previously declared 'void () __arm_streaming', which has different SME function attributes}} +// expected-cpp-note@-2 {{previous declaration is here}} +// expected-error@+3 {{function declared 'void (void)' was previously declared 'void (void) __arm_streaming', which has different SME function attributes}} +// expected-note@-4 {{previous declaration is here}} +__attribute__((target_version("default"))) +void cannot_work_version(void) {} + + +// expected-cpp-error@+2 {{streaming function cannot be multi-versioned}} +// expected-error@+1 {{streaming function cannot be multi-versioned}} +__attribute__((target_clones("sme2"))) +void cannot_work_clones(void) __arm_streaming {} + + +__attribute__((target("sme2"))) +void just_fine_streaming(void) __arm_streaming {} +__attribute__((target_version("sme2"))) +void just_fine(void) { just_fine_streaming(); } +__attribute__((target_version("default"))) +void just_fine(void) {} + + +__arm_locally_streaming +__attribute__((target_version("sme2"))) +void just_fine_locally_streaming(void) {} +__attribute__((target_version("default"))) +void just_fine_locally_streaming(void) {} + + +void fmv_caller() { + cannot_work_version(); + cannot_work_clones(); + just_fine(); + just_fine_locally_streaming(); +} diff --git a/clang/test/Sema/aarch64-tme-errors.c b/clang/test/Sema/aarch64-tme-errors.c index 26e931b62bcb7d92bc4c18b9f6285d9db70aaa7c..1cb6f69035141d8692ceec44889f6cd5d63c7b8f 100644 --- a/clang/test/Sema/aarch64-tme-errors.c +++ b/clang/test/Sema/aarch64-tme-errors.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple aarch64-eabi -verify %s +// RUN: %clang_cc1 -triple aarch64 -verify %s #include "arm_acle.h" diff --git a/clang/test/Sema/aarch64-tme-tcancel-errors.c b/clang/test/Sema/aarch64-tme-tcancel-errors.c index 4fcf6817f090228e965712566c563e880dcd12c0..365bf81cab2d641aed151120cf49a7121dfffc46 100644 --- a/clang/test/Sema/aarch64-tme-tcancel-errors.c +++ b/clang/test/Sema/aarch64-tme-tcancel-errors.c @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -triple aarch64-eabi -target-feature +tme -verify %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +tme -verify %s void t_cancel_const(unsigned short u) { __builtin_arm_tcancel(u); // expected-error{{argument to '__builtin_arm_tcancel' must be a constant integer}} } -// RUN: %clang_cc1 -triple aarch64-eabi -target-feature +tme -verify %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +tme -verify %s void t_cancel_range(void) { __builtin_arm_tcancel(0x12345u); // expected-error{{argument value 74565 is outside the valid range [0, 65535]}} } diff --git a/clang/test/Sema/conversion-64-32.c b/clang/test/Sema/conversion-64-32.c index dc417edcbc21683f888902f7571bc953bcc84dd6..c172dd109f3be2e9b0be23875acc0794c438af65 100644 --- a/clang/test/Sema/conversion-64-32.c +++ b/clang/test/Sema/conversion-64-32.c @@ -9,9 +9,13 @@ typedef long long long2 __attribute__((__vector_size__(16))); int4 test1(long2 a) { int4 v127 = a; // no warning. - return v127; + return v127; } int test2(long v) { return v / 2; // expected-warning {{implicit conversion loses integer precision: 'long' to 'int'}} } + +char test3(short s) { + return s * 2; // no warning. +} diff --git a/clang/test/Sema/conversion-implicit-int-includes-64-to-32.c b/clang/test/Sema/conversion-implicit-int-includes-64-to-32.c new file mode 100644 index 0000000000000000000000000000000000000000..e22ccbe821f65c1544fd1db345e0396990459f7f --- /dev/null +++ b/clang/test/Sema/conversion-implicit-int-includes-64-to-32.c @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wimplicit-int-conversion -triple x86_64-apple-darwin %s + +int test0(long v) { + return v; // expected-warning {{implicit conversion loses integer precision}} +} + +typedef int int4 __attribute__ ((vector_size(16))); +typedef long long long2 __attribute__((__vector_size__(16))); + +int4 test1(long2 a) { + int4 v127 = a; // no warning. + return v127; +} + +int test2(long v) { + return v / 2; // expected-warning {{implicit conversion loses integer precision: 'long' to 'int'}} +} + +char test3(short s) { + return s * 2; // expected-warning {{implicit conversion loses integer precision: 'int' to 'char'}} +} diff --git a/clang/test/Sema/ms_predefined_expr.cpp b/clang/test/Sema/ms_predefined_expr.cpp index 9f4eb2763430dd159cd13f01a80f82004fa10953..b42a494beef98f8d8be53b07b1c9d7f8d18f90e1 100644 --- a/clang/test/Sema/ms_predefined_expr.cpp +++ b/clang/test/Sema/ms_predefined_expr.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions +// RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions -fexperimental-new-constant-interpreter using size_t = __SIZE_TYPE__; diff --git a/clang/test/SemaCXX/PR40395.cpp b/clang/test/SemaCXX/PR40395.cpp index 469c86d56209ca111b01714920da510fb3ee5281..ea0fad2018771595b2818b31234da6e97e12051a 100644 --- a/clang/test/SemaCXX/PR40395.cpp +++ b/clang/test/SemaCXX/PR40395.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++17 -fms-extensions -triple=x86_64-pc-win32 -verify %s +// RUN: %clang_cc1 -std=c++17 -fms-extensions -triple=x86_64-pc-win32 -verify %s -fexperimental-new-constant-interpreter // expected-no-diagnostics // PR40395 - ConstantExpr shouldn't cause the template object to infinitely diff --git a/clang/test/SemaCXX/attr-target-mv-warn-unused.cpp b/clang/test/SemaCXX/attr-target-mv-warn-unused.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1901589ef732fb61465343b2e622d76bfc900438 --- /dev/null +++ b/clang/test/SemaCXX/attr-target-mv-warn-unused.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify -Wunused %s + +__attribute__((target("sse3"))) +static int not_used_fmv() { return 1; } +__attribute__((target("avx2"))) +static int not_used_fmv() { return 2; } +__attribute__((target("default"))) +static int not_used_fmv() { return 0; } // expected-warning {{unused function 'not_used_fmv'}} + +__attribute__((target("sse3"))) +static int definitely_used_fmv() { return 1; } +__attribute__((target("avx2"))) +static int definitely_used_fmv() { return 2; } +__attribute__((target("default"))) +static int definitely_used_fmv() { return 0; } +int definite_user() { return definitely_used_fmv(); } diff --git a/clang/test/SemaCXX/compound-literal.cpp b/clang/test/SemaCXX/compound-literal.cpp index 5957099de53af36b01369898f50608372af40353..a3d3b9faa9fee9ecd3fa2f9fd064a957ebe1c06b 100644 --- a/clang/test/SemaCXX/compound-literal.cpp +++ b/clang/test/SemaCXX/compound-literal.cpp @@ -3,6 +3,7 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -ast-dump %s > %t-11 // RUN: FileCheck --input-file=%t-11 %s // RUN: FileCheck --input-file=%t-11 %s --check-prefix=CHECK-CXX11 +// RUN: %clang_cc1 -verify -std=c++17 %s // http://llvm.org/PR7905 namespace PR7905 { @@ -108,3 +109,23 @@ int computed_with_lambda = [] { return result; }(); #endif + +namespace DynamicFileScopeLiteral { +// This covers the case where we have a file-scope compound literal with a +// non-constant initializer in C++. Previously, we had a bug where Clang forgot +// to consider initializer list elements for bases. +struct Empty {}; +struct Foo : Empty { // expected-note 0+ {{candidate constructor}} + int x; + int y; +}; +int f(); +#if __cplusplus < 201103L +// expected-error@+6 {{non-aggregate type 'Foo' cannot be initialized with an initializer list}} +#elif __cplusplus < 201703L +// expected-error@+4 {{no matching constructor}} +#else +// expected-error@+2 {{initializer element is not a compile-time constant}} +#endif +Foo o = (Foo){ {}, 1, f() }; +} diff --git a/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp b/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp index 00a39f9f03b79cddb9ce18b125abd4ab9ec6d1ef..71e55c8290ee4a2998c5794c16420b5ac44eee54 100644 --- a/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp +++ b/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s -fexperimental-new-constant-interpreter template class normal_iterator {}; diff --git a/clang/test/SemaCXX/conditional-expr.cpp b/clang/test/SemaCXX/conditional-expr.cpp index 9a5e2bac43413dfd7cf76fe79dc1b2fa0f4d6367..01effaa189322bce39b24e42c3771ea96e66ba9b 100644 --- a/clang/test/SemaCXX/conditional-expr.cpp +++ b/clang/test/SemaCXX/conditional-expr.cpp @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify=expected,expected-cxx11 -std=c++11 -Wsign-conversion %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify=expected,expected-cxx11 -std=c++11 -Wsign-conversion %s -fexperimental-new-constant-interpreter // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify=expected,expected-cxx17 -std=c++17 -Wsign-conversion %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify=expected,expected-cxx17 -std=c++17 -Wsign-conversion %s -fexperimental-new-constant-interpreter // C++ rules for ?: are a lot stricter than C rules, and have to take into // account more conversion options. diff --git a/clang/test/SemaCXX/crash-GH10518.cpp b/clang/test/SemaCXX/crash-GH10518.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c5f80afd3cf8b09c52e2c5983e4c5291fc3f2b4 --- /dev/null +++ b/clang/test/SemaCXX/crash-GH10518.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -verify -std=c++98 %s +// RUN: %clang_cc1 -verify -std=c++11 %s +// RUN: %clang_cc1 -verify -std=c++14 %s +// RUN: %clang_cc1 -verify -std=c++17 %s +// RUN: %clang_cc1 -verify -std=c++20 %s +// RUN: %clang_cc1 -verify -std=c++23 %s +// RUN: %clang_cc1 -verify -std=c++2c %s + +// https://github.com/llvm/llvm-project/issues/10518 + +template +class A : public T { +}; + +template +class B : public A { +}; + +template +class B : public A { // expected-error 0-1 {{}} + B(T *t) {} +}; diff --git a/clang/test/SemaCXX/crash-GH49103-2.cpp b/clang/test/SemaCXX/crash-GH49103-2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c17a054c73afc37926b17c8f44a3853c7952b9d --- /dev/null +++ b/clang/test/SemaCXX/crash-GH49103-2.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -verify -std=c++98 %s +// RUN: %clang_cc1 -verify -std=c++11 %s +// RUN: %clang_cc1 -verify -std=c++14 %s +// RUN: %clang_cc1 -verify -std=c++17 %s +// RUN: %clang_cc1 -verify -std=c++20 %s +// RUN: %clang_cc1 -verify -std=c++23 %s +// RUN: %clang_cc1 -verify -std=c++2c %s + +// https://github.com/llvm/llvm-project/issues/49103 + +template struct A; // expected-note 0+ {{}} +struct S : __make_integer_seq { }; // expected-error 0+ {{}} +S s; diff --git a/clang/test/SemaCXX/crash-GH67914.cpp b/clang/test/SemaCXX/crash-GH67914.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fbaeac636c0db1c451f381f9477d316391a4ab35 --- /dev/null +++ b/clang/test/SemaCXX/crash-GH67914.cpp @@ -0,0 +1,78 @@ +// RUN: %clang_cc1 -verify -std=c++98 %s +// RUN: %clang_cc1 -verify -std=c++11 %s +// RUN: %clang_cc1 -verify -std=c++14 %s +// RUN: %clang_cc1 -verify -std=c++17 %s +// RUN: %clang_cc1 -verify -std=c++20 %s +// RUN: %clang_cc1 -verify -std=c++23 %s +// RUN: %clang_cc1 -verify -std=c++2c %s + +// https://github.com/llvm/llvm-project/issues/67914 + +template < typename, int > +struct Mask; + +template < int, class > +struct conditional { + using type = Mask< int, 16 >; // expected-warning 0+ {{}} +}; + +template < class _Then > +struct conditional< 0, _Then > { + using type = _Then; // expected-warning 0+ {{}} +}; + +template < int _Bp, class, class _Then > +using conditional_t = typename conditional< _Bp, _Then >::type; // expected-warning 0+ {{}} + +template < typename, int > +struct Array; + +template < typename, int, bool, typename > +struct StaticArrayImpl; + +template < typename Value_, int Size_ > +struct Mask : StaticArrayImpl< Value_, Size_, 1, Mask< Value_, Size_ > > { // expected-note 0+ {{}} + template < typename T1 > + Mask(T1) {} // expected-note 0+ {{}} +}; + +template < typename T > +void load(typename T::MaskType mask) { + T::load_(mask); // expected-note 0+ {{}} +} + +template < typename Value_, int IsMask_, typename Derived_ > +struct StaticArrayImpl< Value_, 32, IsMask_, Derived_ > { + using Array1 = conditional_t< IsMask_, void, Array< Value_, 16 > >; // expected-warning 0+ {{}} + + template < typename Mask > + static Derived_ load_(Mask mask) { + return Derived_{load< Array1 >(mask.a1), Mask{}}; // expected-error 0+ {{}} + } + + Array1 a1; +}; + +template < typename Derived_ > +struct KMaskBase; + +template < typename Derived_ > +struct StaticArrayImpl< float, 16, 0, Derived_ > { + template < typename Mask > + static Derived_ load_(Mask mask); +}; + +template < typename Derived_ > +struct StaticArrayImpl< float, 16, 1, Mask< float, 16 > > : KMaskBase< Derived_ > {}; // expected-error 0+ {{}} + +template < typename Derived_ > +struct StaticArrayImpl< int, 16, 1, Derived_ > {}; + +template < typename Value_, int Size_ > +struct Array : StaticArrayImpl< Value_, Size_, 0, Array< Value_, Size_ > > { + using MaskType = Mask< Value_, Size_ >; // expected-warning 0+ {{}} +}; + +void test11_load_masked() { + load< Array< float, 32 > >{} == 0; // expected-error 0+ {{}} expected-warning 0+ {{}} expected-note 0+ {{}} +} diff --git a/clang/test/SemaCXX/crash-GH78388.cpp b/clang/test/SemaCXX/crash-GH78388.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cdec4d5bedef4abb67518b55e954e2f9116bc04d --- /dev/null +++ b/clang/test/SemaCXX/crash-GH78388.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -verify -std=c++98 %s +// RUN: %clang_cc1 -verify -std=c++11 %s +// RUN: %clang_cc1 -verify -std=c++14 %s +// RUN: %clang_cc1 -verify -std=c++17 %s +// RUN: %clang_cc1 -verify -std=c++20 %s +// RUN: %clang_cc1 -verify -std=c++23 %s +// RUN: %clang_cc1 -verify -std=c++2c %s + +// https://github.com/llvm/llvm-project/issues/78388 + +typedef mbstate_t; // expected-error 0+ {{}} expected-note 0+ {{}} + template < typename , typename , typename > + class a // expected-error 0+ {{}} + class b { // expected-error 0+ {{}} + namespace { // expected-note 0+ {{}} expected-note 0+ {{}} + template < typename c > b::operator=() { // expected-error 0+ {{}} expected-note 0+ {{}} + struct :a< c, char, stdmbstate_t > d // expected-error 0+ {{}} expected-warning 0+ {{}} diff --git a/clang/test/SemaCXX/expression-traits.cpp b/clang/test/SemaCXX/expression-traits.cpp index a76f0c4a6175ffc6678658a5c48ac9c6c3b46ced..64ddca091e9482fe9fc6b06782afa2c79ecbdb36 100644 --- a/clang/test/SemaCXX/expression-traits.cpp +++ b/clang/test/SemaCXX/expression-traits.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify -fcxx-exceptions %s +// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify -fcxx-exceptions %s -fexperimental-new-constant-interpreter // // Tests for "expression traits" intrinsics such as __is_lvalue_expr. diff --git a/clang/test/SemaCXX/ms-uuid.cpp b/clang/test/SemaCXX/ms-uuid.cpp index 21f93ecc3fa20d15bf17edb82366e821c9c7115c..172e036e15f3fbf5a52f3f96c2d7fc7cf983b917 100644 --- a/clang/test/SemaCXX/ms-uuid.cpp +++ b/clang/test/SemaCXX/ms-uuid.cpp @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -Wno-deprecated-declarations +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -Wno-deprecated-declarations -fexperimental-new-constant-interpreter // RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify -fms-extensions %s -Wno-deprecated-declarations +// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify -fms-extensions %s -Wno-deprecated-declarations -fexperimental-new-constant-interpreter typedef struct _GUID { __UINT32_TYPE__ Data1; diff --git a/clang/test/SemaCXX/self-comparison.cpp b/clang/test/SemaCXX/self-comparison.cpp index 72127f110241281e235a40e3d88dc207a4154a82..c3c875565ff1dbab1b240ed5e9176925994bd5ba 100644 --- a/clang/test/SemaCXX/self-comparison.cpp +++ b/clang/test/SemaCXX/self-comparison.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++2a +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++2a -fexperimental-new-constant-interpreter int foo(int x) { return x == x; // expected-warning {{self-comparison always evaluates to true}} diff --git a/clang/test/SemaCXX/warn-overaligned-type-thrown.cpp b/clang/test/SemaCXX/warn-overaligned-type-thrown.cpp index 9f2386ddc3c61cfe60c0f7345b53a7454096245f..800783f6d92bd3e76d17b73bf552244691b93ced 100644 --- a/clang/test/SemaCXX/warn-overaligned-type-thrown.cpp +++ b/clang/test/SemaCXX/warn-overaligned-type-thrown.cpp @@ -9,7 +9,7 @@ // RUN: %clang_cc1 -triple arm64-apple-tvos12 -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s // RUN: %clang_cc1 -triple arm64-apple-watchos5 -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s // RUN: %clang_cc1 -triple arm-linux-androideabi -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s -// RUN: %clang_cc1 -triple aarch64-linux-gnueabi -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s +// RUN: %clang_cc1 -triple aarch64 -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s // RUN: %clang_cc1 -triple mipsel-linux-gnu -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s // RUN: %clang_cc1 -triple mips64el-linux-gnu -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s // RUN: %clang_cc1 -triple wasm32-unknown-unknown -verify -fsyntax-only -std=c++11 -fcxx-exceptions -fexceptions %s diff --git a/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp b/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp index bda6a65c02168b35fecfa835cf4d92bf6c96fb0e..d54b394df4eb849d44013f0329dbdddbbef1e458 100644 --- a/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp +++ b/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -D AVOID %s -// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s -// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow-all %s +// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx14 -fsyntax-only -Wshadow -D AVOID %s +// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx14 -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s +// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx14 -fsyntax-only -Wshadow-all %s // RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wshadow-all %s // RUN: %clang_cc1 -std=c++20 -verify -fsyntax-only -Wshadow-all %s @@ -179,3 +179,89 @@ void f() { #endif } } + +namespace GH71976 { +#ifdef AVOID +struct A { + int b = 5; + int foo() { + return [b = b]() { return b; }(); // no -Wshadow diagnostic, init-capture does not shadow b due to not capturing this + } +}; + +struct B { + int a; + void foo() { + auto b = [a = this->a] {}; // no -Wshadow diagnostic, init-capture does not shadow a due to not capturing his + } +}; + +struct C { + int b = 5; + int foo() { + return [a = b]() { + return [=, b = a]() { // no -Wshadow diagnostic, init-capture does not shadow b due to outer lambda + return b; + }(); + }(); + } +}; + +#else +struct A { + int b = 5; // expected-note {{previous}} + int foo() { + return [b = b]() { return b; }(); // expected-warning {{declaration shadows a field}} + } +}; + +struct B { + int a; // expected-note {{previous}} + void foo() { + auto b = [a = this->a] {}; // expected-warning {{declaration shadows a field}} + } +}; + +struct C { + int b = 5; // expected-note {{previous}} + int foo() { + return [a = b]() { + return [=, b = a]() { // expected-warning {{declaration shadows a field}} + return b; + }(); + }(); + } +}; + +struct D { + int b = 5; // expected-note {{previous}} + int foo() { + return [b = b, this]() { return b; }(); // expected-warning {{declaration shadows a field}} + } +}; + +struct E { + int b = 5; + int foo() { + return [a = b]() { // expected-note {{previous}} + return [=, a = a]() { // expected-warning {{shadows a local}} + return a; + }(); + }(); + } +}; + +#endif + +struct S { + int a ; +}; + +int foo() { + auto [a] = S{0}; // expected-note {{previous}} \ + // cxx14-warning {{decomposition declarations are a C++17 extension}} + [a = a] () { // expected-warning {{declaration shadows a structured binding}} + }(); +} + +} diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90c11b1be95c25bea7b34da5c065d9e2ddafd093 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage \ +// RUN: -fsafe-buffer-usage-suggestions \ +// RUN: -verify %s + +// CHECK-NOT: [-Wunsafe-buffer-usage] + + +void foo(unsigned idx) { + int buffer[10]; // expected-warning{{'buffer' is an unsafe buffer that does not perform bounds checks}} + // expected-note@-1{{change type of 'buffer' to 'std::array' to label it for hardening}} + buffer[idx] = 0; // expected-note{{used in buffer access here}} +} + +int global_buffer[10]; // expected-warning{{'global_buffer' is an unsafe buffer that does not perform bounds checks}} +void foo2(unsigned idx) { + global_buffer[idx] = 0; // expected-note{{used in buffer access here}} +} + +struct Foo { + int member_buffer[10]; +}; +void foo2(Foo& f, unsigned idx) { + f.member_buffer[idx] = 0; // expected-warning{{unsafe buffer access}} +} diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp index 5fff0854d454673dc9c765f9bb74a4801ba4f725..a5b578b98d4e5b260be8e9d4f1c2083f2a6bdbc8 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp @@ -32,15 +32,6 @@ void foo() { // debug-note{{safe buffers debug: gadget 'ULCArraySubscript' refused to produce a fix}} } -void failed_decl() { - int a[10]; // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}} \ - // debug-note{{safe buffers debug: failed to produce fixit for declaration 'a' : not a pointer}} - - for (int i = 0; i < 10; i++) { - a[i] = i; // expected-note{{used in buffer access here}} - } -} - void failed_multiple_decl() { int *a = new int[4], b; // expected-warning{{'a' is an unsafe pointer used for buffer access}} \ // debug-note{{safe buffers debug: failed to produce fixit for declaration 'a' : multiple VarDecls}} diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-local-var-array.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-local-var-array.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3adfc324dfbe303e951a6733b2dc5da9e8110c45 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-local-var-array.cpp @@ -0,0 +1,228 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN: -fsafe-buffer-usage-suggestions \ +// RUN: -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s +typedef int * Int_ptr_t; +typedef int Int_t; + +void simple(unsigned idx) { + int buffer[10]; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:17}:"std::array buffer" + buffer[idx] = 0; +} + +void array2d(unsigned idx) { + int buffer[10][10]; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]] + buffer[idx][idx] = 0; +} + +void array2d_vla(unsigned sz, unsigned idx) { + int buffer1[10][sz]; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]] + int buffer2[sz][10]; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]] + buffer1[idx][idx] = 0; + buffer2[idx][idx] = 0; +} + +void array2d_assign_from_elem(unsigned idx) { + int buffer[10][10]; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]] + int a = buffer[idx][idx]; +} + +void array2d_use(int *); +void array2d_call(unsigned idx) { + int buffer[10][10]; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]] + array2d_use(buffer[idx]); +} +void array2d_call_vla(unsigned sz, unsigned idx) { + int buffer[10][sz]; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]] + array2d_use(buffer[idx]); +} + +void array2d_typedef(unsigned idx) { + typedef int ten_ints_t[10]; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]] + ten_ints_t buffer[10]; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]] + buffer[idx][idx] = 0; +} + +void whitespace_in_declaration(unsigned idx) { + int buffer_w [ 10 ]; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:35}:"std::array buffer_w" + buffer_w[idx] = 0; +} + +void comments_in_declaration(unsigned idx) { + int /* [A] */ buffer_w /* [B] */ [ /* [C] */ 10 /* [D] */ ] ; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:69}:"std::array buffer_w" + buffer_w[idx] = 0; +} + +void initializer(unsigned idx) { + int buffer[3] = {0}; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:16}:"std::array buffer" + + int buffer2[3] = {0, 1, 2}; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:17}:"std::array buffer2" + + buffer[idx] = 0; + buffer2[idx] = 0; +} + +void auto_size(unsigned idx) { + int buffer[] = {0, 1, 2}; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]] +// FIXME: implement support + + buffer[idx] = 0; +} + +void universal_initialization(unsigned idx) { + int buffer[] {0, 1, 2}; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]] +// FIXME: implement support + + buffer[idx] = 0; +} + +void multi_decl1(unsigned idx) { + int a, buffer[10]; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]] +// FIXME: implement support + + buffer[idx] = 0; +} + +void multi_decl2(unsigned idx) { + int buffer[10], b; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]] +// FIXME: implement support + + buffer[idx] = 0; +} + +void local_array_ptr_to_const(unsigned idx, const int*& a) { + const int * buffer[10] = {a}; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:25}:"std::array buffer" + a = buffer[idx]; +} + +void local_array_const_ptr(unsigned idx, int*& a) { + int * const buffer[10] = {a}; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:25}:"std::array buffer" + + a = buffer[idx]; +} + +void local_array_const_ptr_via_typedef(unsigned idx, int*& a) { + typedef int * const my_const_ptr; + my_const_ptr buffer[10] = {a}; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:26}:"std::array buffer" + + a = buffer[idx]; +} + +void local_array_const_ptr_to_const(unsigned idx, const int*& a) { + const int * const buffer[10] = {a}; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:31}:"std::array buffer" + + a = buffer[idx]; + +} + +template +void unsupported_local_array_in_template(unsigned idx) { + T buffer[10]; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*} + buffer[idx] = 0; +} +// Instantiate the template function to force its analysis. +template void unsupported_local_array_in_template(unsigned); + +typedef unsigned int my_uint; +void typedef_as_elem_type(unsigned idx) { + my_uint buffer[10]; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:21}:"std::array buffer" + buffer[idx] = 0; +} + +void decltype_as_elem_type(unsigned idx) { + int a; + decltype(a) buffer[10]; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:25}:"std::array buffer" + buffer[idx] = 0; +} + +void macro_as_elem_type(unsigned idx) { +#define MY_INT int + MY_INT buffer[10]; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*} +// FIXME: implement support + + buffer[idx] = 0; +#undef MY_INT +} + +void macro_as_identifier(unsigned idx) { +#define MY_BUFFER buffer + int MY_BUFFER[10]; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:20}:"std::array MY_BUFFER" + MY_BUFFER[idx] = 0; +#undef MY_BUFFER +} + +void macro_as_size(unsigned idx) { +#define MY_TEN 10 + int buffer[MY_TEN]; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:21}:"std::array buffer" + buffer[idx] = 0; +#undef MY_TEN +} + +typedef unsigned int my_array[42]; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*} +void typedef_as_array_type(unsigned idx) { + my_array buffer; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*} + buffer[idx] = 0; +} + +void decltype_as_array_type(unsigned idx) { + int buffer[42]; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*} + decltype(buffer) buffer2; +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:.*-[[@LINE-1]]:.*} + buffer2[idx] = 0; +} + +void constant_as_size(unsigned idx) { + const unsigned my_const = 10; + int buffer[my_const]; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:23}:"std::array buffer" + buffer[idx] = 0; +} + +void subscript_negative() { + int buffer[10]; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:17}:"std::array buffer" + + // For constant-size arrays any negative index will lead to buffer underflow. + // std::array::operator[] has unsigned parameter so the value will be casted to unsigned. + // This will very likely be buffer overflow but hardened std::array catch these at runtime. + buffer[-5] = 0; +} + +void subscript_signed(int signed_idx) { + int buffer[10]; +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:17}:"std::array buffer" + + // For constant-size arrays any negative index will lead to buffer underflow. + // std::array::operator[] has unsigned parameter so the value will be casted to unsigned. + // This will very likely be buffer overflow but hardened std::array catches these at runtime. + buffer[signed_idx] = 0; +} diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp index c5f0a9ef929371bc15d1f7e4f4762f3ac9ff082a..67cdf252d6a8b67797b239e0d29ff5a57708db01 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp @@ -61,6 +61,7 @@ void testArraySubscripts(int *p, int **pp) { ); int a[10]; // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}} + // expected-note@-1{{change type of 'a' to 'std::array' to label it for hardening}} int b[10][10]; // expected-warning{{'b' is an unsafe buffer that does not perform bounds checks}} foo(a[1], 1[a], // expected-note2{{used in buffer access here}} @@ -174,6 +175,7 @@ auto file_scope_lambda = [](int *ptr) { void testLambdaCapture() { int a[10]; // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}} int b[10]; // expected-warning{{'b' is an unsafe buffer that does not perform bounds checks}} + // expected-note@-1{{change type of 'b' to 'std::array' to label it for hardening}} int c[10]; auto Lam1 = [a]() { @@ -191,7 +193,9 @@ void testLambdaCapture() { void testLambdaImplicitCapture() { int a[10]; // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}} + // expected-note@-1{{change type of 'a' to 'std::array' to label it for hardening}} int b[10]; // expected-warning{{'b' is an unsafe buffer that does not perform bounds checks}} + // expected-note@-1{{change type of 'b' to 'std::array' to label it for hardening}} auto Lam1 = [=]() { return a[1]; // expected-note{{used in buffer access here}} @@ -344,6 +348,7 @@ template void fArr(T t[]) { // expected-warning@-1{{'t' is an unsafe pointer used for buffer access}} foo(t[1]); // expected-note{{used in buffer access here}} T ar[8]; // expected-warning{{'ar' is an unsafe buffer that does not perform bounds checks}} + // expected-note@-1{{change type of 'ar' to 'std::array' to label it for hardening}} foo(ar[5]); // expected-note{{used in buffer access here}} } diff --git a/clang/test/SemaCXX/warn-unused-filescoped-fmv.cpp b/clang/test/SemaCXX/warn-unused-filescoped-fmv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8c21da5a139f1efe08cfeff94cf455f142dbfde5 --- /dev/null +++ b/clang/test/SemaCXX/warn-unused-filescoped-fmv.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple arm64-apple-darwin -fsyntax-only -verify -Wunused -std=c++98 %s +// RUN: %clang_cc1 -triple arm64-apple-darwin -fsyntax-only -verify -Wunused -std=c++14 %s + +__attribute__((target_version("fp16"))) +static int not_used_fmv(void) { return 1; } +__attribute__((target_version("fp16fml"))) +static int not_used_fmv(void) { return 2; } +__attribute__((target_version("default"))) +static int not_used_fmv(void) { return 0; } // expected-warning {{unused function 'not_used_fmv'}} + + +__attribute__((target_version("fp16"))) +static int definitely_used_fmv(void) { return 1; } +__attribute__((target_version("fp16fml"))) +static int definitely_used_fmv(void) { return 2; } +__attribute__((target_version("default"))) +static int definitely_used_fmv(void) { return 0; } +int definite_user(void) { return definitely_used_fmv(); } diff --git a/clang/test/SemaOpenCL/operators.cl b/clang/test/SemaOpenCL/operators.cl index cf359acd5acb97484ecb1247c238a2b53107c9eb..76a7692a7105c8927c25ad33e551a6ba6ef51018 100644 --- a/clang/test/SemaOpenCL/operators.cl +++ b/clang/test/SemaOpenCL/operators.cl @@ -118,6 +118,6 @@ kernel void pointer_ops(){ bool b = !p; b = p==0; int i; - b = !&i; + b = !&i; // expected-warning {{address of 'i' will always evaluate to 'true'}} b = &i==(int *)1; } diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index 5ee6092bb9bb7f60d6251ddc05d31adbebcfb3a8..e122cea50f7268c9aa50961a37f95fc1af22bd23 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -399,7 +399,8 @@ class ClangFormatDiagConsumer : public DiagnosticConsumer { }; // Returns true on error. -static bool format(StringRef FileName, bool IsSTDIN) { +static bool format(StringRef FileName) { + const bool IsSTDIN = FileName == "-"; if (!OutputXML && Inplace && IsSTDIN) { errs() << "error: cannot use -i when reading from stdin.\n"; return false; @@ -545,24 +546,25 @@ static void PrintVersion(raw_ostream &OS) { } // Dump the configuration. -static int dumpConfig(bool IsSTDIN) { +static int dumpConfig() { std::unique_ptr Code; - - // `FileNames` must have at least "-" in it even if no file was specified. - assert(!FileNames.empty()); - - // Read in the code in case the filename alone isn't enough to detect the - // language. - ErrorOr> CodeOrErr = - MemoryBuffer::getFileOrSTDIN(FileNames[0]); - if (std::error_code EC = CodeOrErr.getError()) { - llvm::errs() << EC.message() << "\n"; - return 1; + // We can't read the code to detect the language if there's no file name. + if (!FileNames.empty()) { + // Read in the code in case the filename alone isn't enough to detect the + // language. + ErrorOr> CodeOrErr = + MemoryBuffer::getFileOrSTDIN(FileNames[0]); + if (std::error_code EC = CodeOrErr.getError()) { + llvm::errs() << EC.message() << "\n"; + return 1; + } + Code = std::move(CodeOrErr.get()); } - Code = std::move(CodeOrErr.get()); - llvm::Expected FormatStyle = - clang::format::getStyle(Style, IsSTDIN ? AssumeFileName : FileNames[0], + clang::format::getStyle(Style, + FileNames.empty() || FileNames[0] == "-" + ? AssumeFileName + : FileNames[0], FallbackStyle, Code ? Code->getBuffer() : ""); if (!FormatStyle) { llvm::errs() << llvm::toString(FormatStyle.takeError()) << "\n"; @@ -682,11 +684,8 @@ int main(int argc, const char **argv) { return 0; } - if (FileNames.empty()) - FileNames.push_back("-"); - if (DumpConfig) - return dumpConfig(FileNames[0] == "-"); + return dumpConfig(); if (!Files.empty()) { std::ifstream ExternalFileOfFiles{std::string(Files)}; @@ -699,7 +698,10 @@ int main(int argc, const char **argv) { errs() << "Clang-formating " << LineNo << " files\n"; } - if (FileNames.size() != 1 && + if (FileNames.empty()) + return clang::format::format("-"); + + if (FileNames.size() > 1 && (!Offsets.empty() || !Lengths.empty() || !LineRanges.empty())) { errs() << "error: -offset, -length and -lines can only be used for " "single file.\n"; @@ -709,14 +711,13 @@ int main(int argc, const char **argv) { unsigned FileNo = 1; bool Error = false; for (const auto &FileName : FileNames) { - const bool IsSTDIN = FileName == "-"; - if (!IsSTDIN && isIgnored(FileName)) + if (isIgnored(FileName)) continue; if (Verbose) { errs() << "Formatting [" << FileNo++ << "/" << FileNames.size() << "] " << FileName << "\n"; } - Error |= clang::format::format(FileName, IsSTDIN); + Error |= clang::format::format(FileName); } return Error ? 1 : 0; } diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp index e9d2c6aad371dbbf75f2e8e072a78bd345b06486..b5c6be3c557bb374c1f5f835d692db80634cae3f 100644 --- a/clang/tools/driver/cc1_main.cpp +++ b/clang/tools/driver/cc1_main.cpp @@ -78,64 +78,6 @@ static void LLVMErrorHandler(void *UserData, const char *Message, } #ifdef CLANG_HAVE_RLIMITS -#if defined(__linux__) && defined(__PIE__) -static size_t getCurrentStackAllocation() { - // If we can't compute the current stack usage, allow for 512K of command - // line arguments and environment. - size_t Usage = 512 * 1024; - if (FILE *StatFile = fopen("/proc/self/stat", "r")) { - // We assume that the stack extends from its current address to the end of - // the environment space. In reality, there is another string literal (the - // program name) after the environment, but this is close enough (we only - // need to be within 100K or so). - unsigned long StackPtr, EnvEnd; - // Disable silly GCC -Wformat warning that complains about length - // modifiers on ignored format specifiers. We want to retain these - // for documentation purposes even though they have no effect. -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat" -#endif - if (fscanf(StatFile, - "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %*lu " - "%*lu %*ld %*ld %*ld %*ld %*ld %*ld %*llu %*lu %*ld %*lu %*lu " - "%*lu %*lu %lu %*lu %*lu %*lu %*lu %*lu %*llu %*lu %*lu %*d %*d " - "%*u %*u %*llu %*lu %*ld %*lu %*lu %*lu %*lu %*lu %*lu %lu %*d", - &StackPtr, &EnvEnd) == 2) { -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif - Usage = StackPtr < EnvEnd ? EnvEnd - StackPtr : StackPtr - EnvEnd; - } - fclose(StatFile); - } - return Usage; -} - -#include - -LLVM_ATTRIBUTE_NOINLINE -static void ensureStackAddressSpace() { - // Linux kernels prior to 4.1 will sometimes locate the heap of a PIE binary - // relatively close to the stack (they are only guaranteed to be 128MiB - // apart). This results in crashes if we happen to heap-allocate more than - // 128MiB before we reach our stack high-water mark. - // - // To avoid these crashes, ensure that we have sufficient virtual memory - // pages allocated before we start running. - size_t Curr = getCurrentStackAllocation(); - const int kTargetStack = DesiredStackSize - 256 * 1024; - if (Curr < kTargetStack) { - volatile char *volatile Alloc = - static_cast(alloca(kTargetStack - Curr)); - Alloc[0] = 0; - Alloc[kTargetStack - Curr - 1] = 0; - } -} -#else -static void ensureStackAddressSpace() {} -#endif - /// Attempt to ensure that we have at least 8MiB of usable stack space. static void ensureSufficientStack() { struct rlimit rlim; @@ -159,10 +101,6 @@ static void ensureSufficientStack() { rlim.rlim_cur != DesiredStackSize) return; } - - // We should now have a stack of size at least DesiredStackSize. Ensure - // that we can actually use that much, if necessary. - ensureStackAddressSpace(); } #else static void ensureSufficientStack() {} diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index bc398fa0731f160b37fafbac3c47b94c7c2531b4..a55e06500d9d9202132d0d12b46cd3d88ccbacae 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -89,10 +89,15 @@ struct AssemblerInvocation { /// @{ std::vector IncludePaths; + LLVM_PREFERRED_TYPE(bool) unsigned NoInitialTextSection : 1; + LLVM_PREFERRED_TYPE(bool) unsigned SaveTemporaryLabels : 1; + LLVM_PREFERRED_TYPE(bool) unsigned GenDwarfForAssembly : 1; + LLVM_PREFERRED_TYPE(bool) unsigned RelaxELFRelocations : 1; + LLVM_PREFERRED_TYPE(bool) unsigned Dwarf64 : 1; unsigned DwarfVersion; std::string DwarfDebugFlags; @@ -117,7 +122,9 @@ struct AssemblerInvocation { FT_Obj ///< Object file output. }; FileType OutputType; + LLVM_PREFERRED_TYPE(bool) unsigned ShowHelp : 1; + LLVM_PREFERRED_TYPE(bool) unsigned ShowVersion : 1; /// @} @@ -125,19 +132,28 @@ struct AssemblerInvocation { /// @{ unsigned OutputAsmVariant; + LLVM_PREFERRED_TYPE(bool) unsigned ShowEncoding : 1; + LLVM_PREFERRED_TYPE(bool) unsigned ShowInst : 1; /// @} /// @name Assembler Options /// @{ + LLVM_PREFERRED_TYPE(bool) unsigned RelaxAll : 1; + LLVM_PREFERRED_TYPE(bool) unsigned NoExecStack : 1; + LLVM_PREFERRED_TYPE(bool) unsigned FatalWarnings : 1; + LLVM_PREFERRED_TYPE(bool) unsigned NoWarn : 1; + LLVM_PREFERRED_TYPE(bool) unsigned NoTypeCheck : 1; + LLVM_PREFERRED_TYPE(bool) unsigned IncrementalLinkerCompatible : 1; + LLVM_PREFERRED_TYPE(bool) unsigned EmbedBitcode : 1; /// Whether to emit DWARF unwind info. @@ -145,6 +161,7 @@ struct AssemblerInvocation { // Whether to emit compact-unwind for non-canonical entries. // Note: maybe overriden by other constraints. + LLVM_PREFERRED_TYPE(bool) unsigned EmitCompactUnwindNonCanonical : 1; /// The name of the relocation model to use. diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index e5c0971996e017bef820736059afe37acea417cc..4ded92cbe9aea48df0a6557a62dca220f8017112 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -6114,6 +6114,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("attribute(aligned)"); case CXCursor_ConceptDecl: return cxstring::createRef("ConceptDecl"); + case CXCursor_OpenACCComputeConstruct: + return cxstring::createRef("OpenACCComputeConstruct"); } llvm_unreachable("Unhandled CXCursorKind"); diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 01b8a23f6eac3ba6cb90616cb9f6bed5cc3b4d09..454bf75498618962812d27c4cb6dc734baec62ac 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -870,6 +870,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::OMPParallelGenericLoopDirectiveClass: K = CXCursor_OMPParallelGenericLoopDirective; break; + case Stmt::OpenACCComputeConstructClass: + K = CXCursor_OpenACCComputeConstruct; + break; case Stmt::OMPTargetParallelGenericLoopDirectiveClass: K = CXCursor_OMPTargetParallelGenericLoopDirective; break; diff --git a/clang/tools/libclang/Indexing.cpp b/clang/tools/libclang/Indexing.cpp index 17d393ef80842583d3156410846b79bd75f9be22..05d88452209fb38aef79c7e37210d160d64dedc0 100644 --- a/clang/tools/libclang/Indexing.cpp +++ b/clang/tools/libclang/Indexing.cpp @@ -261,12 +261,13 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override { bool isImport = (IncludeTok.is(tok::identifier) && IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import); DataConsumer.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled, - Imported); + ModuleImported); } /// MacroDefined - This hook is called whenever a macro definition is seen. diff --git a/clang/tools/scan-build/man/scan-build.1 b/clang/tools/scan-build/man/scan-build.1 index 29edbca1fc63881a525fd1f268d5edfce33934e7..e2b37f6062dbc0b0ccb6b3db1640f8bd1e943a86 100644 --- a/clang/tools/scan-build/man/scan-build.1 +++ b/clang/tools/scan-build/man/scan-build.1 @@ -2,9 +2,9 @@ .\" See https://llvm.org/LICENSE.txt for license information. .\" SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception .\" $Id$ -.Dd Sep 21, 2023 +.Dd Feb 10, 2024 .Dt SCAN-BUILD 1 -.Os "clang" "18" +.Os "clang" "19" .Sh NAME .Nm scan-build .Nd Clang static analyzer diff --git a/clang/unittests/AST/ASTExprTest.cpp b/clang/unittests/AST/ASTExprTest.cpp index ec75492ccff8e44a5010a2fd9ca5f86c67ccc0e8..5ec6aea8edba38769a3ca52171f60456d6e06a78 100644 --- a/clang/unittests/AST/ASTExprTest.cpp +++ b/clang/unittests/AST/ASTExprTest.cpp @@ -20,17 +20,37 @@ using namespace clang; +using clang::ast_matchers::cxxRecordDecl; +using clang::ast_matchers::hasName; +using clang::ast_matchers::match; +using clang::ast_matchers::varDecl; +using clang::tooling::buildASTFromCode; + +static IntegerLiteral *createIntLiteral(ASTContext &Ctx, uint32_t Value) { + const int numBits = 32; + return IntegerLiteral::Create(Ctx, llvm::APInt(numBits, Value), Ctx.IntTy, + {}); +} + +const CXXRecordDecl *getCXXRecordDeclNode(ASTUnit *AST, + const std::string &Name) { + auto Result = + match(cxxRecordDecl(hasName(Name)).bind("record"), AST->getASTContext()); + EXPECT_FALSE(Result.empty()); + return Result[0].getNodeAs("record"); +} + +const VarDecl *getVariableNode(ASTUnit *AST, const std::string &Name) { + auto Result = match(varDecl(hasName(Name)).bind("var"), AST->getASTContext()); + EXPECT_EQ(Result.size(), 1u); + return Result[0].getNodeAs("var"); +} + TEST(ASTExpr, IgnoreExprCallbackForwarded) { constexpr char Code[] = ""; auto AST = tooling::buildASTFromCodeWithArgs(Code, /*Args=*/{"-std=c++20"}); ASTContext &Ctx = AST->getASTContext(); - auto createIntLiteral = [&](uint32_t Value) -> IntegerLiteral * { - const int numBits = 32; - return IntegerLiteral::Create(Ctx, llvm::APInt(numBits, Value), - Ctx.UnsignedIntTy, {}); - }; - struct IgnoreParens { Expr *operator()(Expr *E) & { return nullptr; } Expr *operator()(Expr *E) && { @@ -42,7 +62,7 @@ TEST(ASTExpr, IgnoreExprCallbackForwarded) { }; { - auto *IntExpr = createIntLiteral(10); + auto *IntExpr = createIntLiteral(Ctx, 10); ParenExpr *PE = new (Ctx) ParenExpr(SourceLocation{}, SourceLocation{}, IntExpr); EXPECT_EQ(IntExpr, IgnoreExprNodes(PE, IgnoreParens{})); @@ -50,9 +70,41 @@ TEST(ASTExpr, IgnoreExprCallbackForwarded) { { IgnoreParens CB{}; - auto *IntExpr = createIntLiteral(10); + auto *IntExpr = createIntLiteral(Ctx, 10); ParenExpr *PE = new (Ctx) ParenExpr(SourceLocation{}, SourceLocation{}, IntExpr); EXPECT_EQ(nullptr, IgnoreExprNodes(PE, CB)); } } + +TEST(ASTExpr, InitListIsConstantInitialized) { + auto AST = buildASTFromCode(R"cpp( + struct Empty {}; + struct Foo : Empty { int x, y; }; + int gv; + )cpp"); + ASTContext &Ctx = AST->getASTContext(); + const CXXRecordDecl *Empty = getCXXRecordDeclNode(AST.get(), "Empty"); + const CXXRecordDecl *Foo = getCXXRecordDeclNode(AST.get(), "Foo"); + + SourceLocation Loc{}; + InitListExpr *BaseInit = new (Ctx) InitListExpr(Ctx, Loc, {}, Loc); + BaseInit->setType(Ctx.getRecordType(Empty)); + Expr *Exprs[3] = { + BaseInit, + createIntLiteral(Ctx, 13), + createIntLiteral(Ctx, 42), + }; + InitListExpr *FooInit = new (Ctx) InitListExpr(Ctx, Loc, Exprs, Loc); + FooInit->setType(Ctx.getRecordType(Foo)); + EXPECT_TRUE(FooInit->isConstantInitializer(Ctx, false)); + + // Replace the last initializer with something non-constant and make sure + // this returns false. Previously we had a bug where we didn't count base + // initializers, and only iterated over fields. + const VarDecl *GV = getVariableNode(AST.get(), "gv"); + auto *Ref = new (Ctx) DeclRefExpr(Ctx, const_cast(GV), false, + Ctx.IntTy, VK_LValue, Loc); + (void)FooInit->updateInit(Ctx, 2, Ref); + EXPECT_FALSE(FooInit->isConstantInitializer(Ctx, false)); +} diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 8bbb04024dcce69cf336f5b9a7aff45775abd392..4b3b3511f848e8f579388e7eff8286000cbce6a9 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2093,7 +2093,7 @@ TEST(TransferTest, TemporaryObject) { TEST(TransferTest, ElidableConstructor) { // This test is effectively the same as TransferTest.TemporaryObject, but - // the code is compiled as C++ 14. + // the code is compiled as C++14. std::string Code = R"( struct A { int Bar; @@ -2313,6 +2313,42 @@ TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) { ASTContext &ASTCtx) {}); } +TEST(TransferTest, AssignmentOperatorReturnsVoid) { + // This is a crash repro. + std::string Code = R"( + struct S { + void operator=(S&& other); + }; + void target() { + S s; + s = S(); + // [[p]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) {}); +} + +TEST(TransferTest, AssignmentOperatorReturnsByValue) { + // This is a crash repro. + std::string Code = R"( + struct S { + S operator=(S&& other); + }; + void target() { + S s; + s = S(); + // [[p]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) {}); +} + TEST(TransferTest, CopyConstructor) { std::string Code = R"( struct A { diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp index 73fb4063d92be93fa22ab623b6a891e5cd731d10..b6e4973fd7cb2b1a524c84e4d6043a2e96a96e60 100644 --- a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp @@ -770,12 +770,17 @@ constexpr bool operator!=(const optional &lhs, const optional &rhs); template constexpr bool operator==(const optional &opt, nullopt_t); + +// C++20 and later do not define the following overloads because they are +// provided by rewritten candidates instead. +#if __cplusplus < 202002L template constexpr bool operator==(nullopt_t, const optional &opt); template constexpr bool operator!=(const optional &opt, nullopt_t); template constexpr bool operator!=(nullopt_t, const optional &opt); +#endif // __cplusplus < 202002L template constexpr bool operator==(const optional &opt, const U &value); @@ -1289,6 +1294,15 @@ protected: template void ExpectDiagnosticsFor(std::string SourceCode, FuncDeclMatcher FuncMatcher) { + // Run in C++17 and C++20 mode to cover differences in the AST between modes + // (e.g. C++20 can contain `CXXRewrittenBinaryOperator`). + for (const char *CxxMode : {"-std=c++17", "-std=c++20"}) + ExpectDiagnosticsFor(SourceCode, FuncMatcher, CxxMode); + } + + template + void ExpectDiagnosticsFor(std::string SourceCode, FuncDeclMatcher FuncMatcher, + const char *CxxMode) { ReplaceAllOccurrences(SourceCode, "$ns", GetParam().NamespaceName); ReplaceAllOccurrences(SourceCode, "$optional", GetParam().TypeName); @@ -1332,7 +1346,7 @@ protected: llvm::move(EltDiagnostics, std::back_inserter(Diagnostics)); }) .withASTBuildArgs( - {"-fsyntax-only", "-std=c++17", "-Wno-undefined-inline"}) + {"-fsyntax-only", CxxMode, "-Wno-undefined-inline"}) .withASTBuildVirtualMappedFiles( tooling::FileContentMappings(Headers.begin(), Headers.end())), /*VerifyResults=*/[&Diagnostics]( diff --git a/clang/unittests/Basic/SourceManagerTest.cpp b/clang/unittests/Basic/SourceManagerTest.cpp index 557281499998ae1b057fdc64177e8b11bd084262..45840f5188cdcdf5679b0468a3df2c3bf686d95b 100644 --- a/clang/unittests/Basic/SourceManagerTest.cpp +++ b/clang/unittests/Basic/SourceManagerTest.cpp @@ -530,6 +530,7 @@ struct MacroAction { SourceLocation Loc; std::string Name; + LLVM_PREFERRED_TYPE(Kind) unsigned MAKind : 3; MacroAction(SourceLocation Loc, StringRef Name, unsigned K) diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 7493b0a4450f9b05b530b6d2d1bf640b4ca8b29b..ee8a55680753f4ee5ab2186971aef1d599a69a1d 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -678,6 +678,22 @@ TEST(ConfigParseTest, ParsesConfiguration) { BraceWrapping.AfterControlStatement, FormatStyle::BWACS_Never); Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_All; + CHECK_PARSE("BreakAfterReturnType: None", AlwaysBreakAfterReturnType, + FormatStyle::RTBS_None); + CHECK_PARSE("BreakAfterReturnType: Automatic", AlwaysBreakAfterReturnType, + FormatStyle::RTBS_Automatic); + CHECK_PARSE("BreakAfterReturnType: ExceptShortType", + AlwaysBreakAfterReturnType, FormatStyle::RTBS_ExceptShortType); + CHECK_PARSE("BreakAfterReturnType: All", AlwaysBreakAfterReturnType, + FormatStyle::RTBS_All); + CHECK_PARSE("BreakAfterReturnType: TopLevel", AlwaysBreakAfterReturnType, + FormatStyle::RTBS_TopLevel); + CHECK_PARSE("BreakAfterReturnType: AllDefinitions", + AlwaysBreakAfterReturnType, FormatStyle::RTBS_AllDefinitions); + CHECK_PARSE("BreakAfterReturnType: TopLevelDefinitions", + AlwaysBreakAfterReturnType, + FormatStyle::RTBS_TopLevelDefinitions); + // For backward compatibility: CHECK_PARSE("AlwaysBreakAfterReturnType: None", AlwaysBreakAfterReturnType, FormatStyle::RTBS_None); CHECK_PARSE("AlwaysBreakAfterReturnType: Automatic", @@ -694,19 +710,32 @@ TEST(ConfigParseTest, ParsesConfiguration) { AlwaysBreakAfterReturnType, FormatStyle::RTBS_TopLevelDefinitions); - Style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; + Style.BreakTemplateDeclarations = FormatStyle::BTDS_Yes; + CHECK_PARSE("BreakTemplateDeclarations: Leave", BreakTemplateDeclarations, + FormatStyle::BTDS_Leave); + CHECK_PARSE("BreakTemplateDeclarations: No", BreakTemplateDeclarations, + FormatStyle::BTDS_No); + CHECK_PARSE("BreakTemplateDeclarations: MultiLine", BreakTemplateDeclarations, + FormatStyle::BTDS_MultiLine); + CHECK_PARSE("BreakTemplateDeclarations: Yes", BreakTemplateDeclarations, + FormatStyle::BTDS_Yes); + CHECK_PARSE("BreakTemplateDeclarations: false", BreakTemplateDeclarations, + FormatStyle::BTDS_MultiLine); + CHECK_PARSE("BreakTemplateDeclarations: true", BreakTemplateDeclarations, + FormatStyle::BTDS_Yes); + // For backward compatibility: CHECK_PARSE("AlwaysBreakTemplateDeclarations: Leave", - AlwaysBreakTemplateDeclarations, FormatStyle::BTDS_Leave); - CHECK_PARSE("AlwaysBreakTemplateDeclarations: No", - AlwaysBreakTemplateDeclarations, FormatStyle::BTDS_No); + BreakTemplateDeclarations, FormatStyle::BTDS_Leave); + CHECK_PARSE("AlwaysBreakTemplateDeclarations: No", BreakTemplateDeclarations, + FormatStyle::BTDS_No); CHECK_PARSE("AlwaysBreakTemplateDeclarations: MultiLine", - AlwaysBreakTemplateDeclarations, FormatStyle::BTDS_MultiLine); - CHECK_PARSE("AlwaysBreakTemplateDeclarations: Yes", - AlwaysBreakTemplateDeclarations, FormatStyle::BTDS_Yes); + BreakTemplateDeclarations, FormatStyle::BTDS_MultiLine); + CHECK_PARSE("AlwaysBreakTemplateDeclarations: Yes", BreakTemplateDeclarations, + FormatStyle::BTDS_Yes); CHECK_PARSE("AlwaysBreakTemplateDeclarations: false", - AlwaysBreakTemplateDeclarations, FormatStyle::BTDS_MultiLine); + BreakTemplateDeclarations, FormatStyle::BTDS_MultiLine); CHECK_PARSE("AlwaysBreakTemplateDeclarations: true", - AlwaysBreakTemplateDeclarations, FormatStyle::BTDS_Yes); + BreakTemplateDeclarations, FormatStyle::BTDS_Yes); Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; CHECK_PARSE("AlwaysBreakAfterDefinitionReturnType: None", diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index b1a2247bb85d6f180dd6963883587d0f7e3f9ea5..13937a15fdaee2eb3f49ee63b98b4c701ee20e32 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -10638,7 +10638,7 @@ TEST_F(FormatTest, WrapsTemplateDeclarations) { " const typename aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaa);"); FormatStyle AlwaysBreak = getLLVMStyle(); - AlwaysBreak.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; + AlwaysBreak.BreakTemplateDeclarations = FormatStyle::BTDS_Yes; verifyFormat("template \nclass C {};", AlwaysBreak); verifyFormat("template \nvoid f();", AlwaysBreak); verifyFormat("template \nvoid f() {}", AlwaysBreak); @@ -10667,7 +10667,7 @@ TEST_F(FormatTest, WrapsTemplateDeclarations) { "};"); FormatStyle NeverBreak = getLLVMStyle(); - NeverBreak.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_No; + NeverBreak.BreakTemplateDeclarations = FormatStyle::BTDS_No; verifyFormat("template class C {};", NeverBreak); verifyFormat("template void f();", NeverBreak); verifyFormat("template void f() {}", NeverBreak); @@ -10699,7 +10699,7 @@ TEST_F(FormatTest, WrapsTemplateDeclarations) { NeverBreak); auto Style = getLLVMStyle(); - Style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Leave; + Style.BreakTemplateDeclarations = FormatStyle::BTDS_Leave; verifyNoChange("template \n" "class C {};", @@ -11297,7 +11297,7 @@ TEST_F(FormatTest, UnderstandsFunctionRefQualification) { verifyFormat("SomeType MemberFunction( const Deleted & ) &;", Spaces); FormatStyle BreakTemplate = getLLVMStyle(); - BreakTemplate.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; + BreakTemplate.BreakTemplateDeclarations = FormatStyle::BTDS_Yes; verifyFormat("struct f {\n" " template \n" @@ -11330,8 +11330,7 @@ TEST_F(FormatTest, UnderstandsFunctionRefQualification) { BreakTemplate); FormatStyle AlignLeftBreakTemplate = getLLVMStyle(); - AlignLeftBreakTemplate.AlwaysBreakTemplateDeclarations = - FormatStyle::BTDS_Yes; + AlignLeftBreakTemplate.BreakTemplateDeclarations = FormatStyle::BTDS_Yes; AlignLeftBreakTemplate.PointerAlignment = FormatStyle::PAS_Left; verifyFormat("struct f {\n" @@ -26973,6 +26972,7 @@ TEST_F(FormatTest, RemoveParentheses) { EXPECT_EQ(Style.RemoveParentheses, FormatStyle::RPS_Leave); Style.RemoveParentheses = FormatStyle::RPS_MultipleParentheses; + verifyFormat("#define Foo(...) foo((__VA_ARGS__))", Style); verifyFormat("int x __attribute__((aligned(16))) = 0;", Style); verifyFormat("decltype((foo->bar)) baz;", Style); verifyFormat("class __declspec(dllimport) X {};", @@ -27007,6 +27007,7 @@ TEST_F(FormatTest, RemoveParentheses) { verifyFormat("return (({ 0; }));", "return ((({ 0; })));", Style); Style.RemoveParentheses = FormatStyle::RPS_ReturnStatement; + verifyFormat("#define Return0 return (0);", Style); verifyFormat("return 0;", "return (0);", Style); verifyFormat("co_return 0;", "co_return ((0));", Style); verifyFormat("return 0;", "return (((0)));", Style); diff --git a/clang/unittests/Format/QualifierFixerTest.cpp b/clang/unittests/Format/QualifierFixerTest.cpp index 324366ca7f5e51123c45e37c8767637d0cda29cc..0aa755acfc8213ce4db78f4c1917ae8f9ef8eefe 100644 --- a/clang/unittests/Format/QualifierFixerTest.cpp +++ b/clang/unittests/Format/QualifierFixerTest.cpp @@ -1055,6 +1055,7 @@ TEST_F(QualifierFixerTest, IsQualifierType) { auto Tokens = annotate( "const static inline auto restrict int double long constexpr friend"); + ASSERT_EQ(Tokens.size(), 11u) << Tokens; EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( Tokens[0], ConfiguredTokens)); @@ -1089,6 +1090,7 @@ TEST_F(QualifierFixerTest, IsQualifierType) { EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isQualifierOrType(Tokens[9])); auto NotTokens = annotate("for while do Foo Bar "); + ASSERT_EQ(NotTokens.size(), 6u) << Tokens; EXPECT_FALSE(LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType( NotTokens[0], ConfiguredTokens)); @@ -1120,6 +1122,7 @@ TEST_F(QualifierFixerTest, IsQualifierType) { TEST_F(QualifierFixerTest, IsMacro) { auto Tokens = annotate("INT INTPR Foo int"); + ASSERT_EQ(Tokens.size(), 5u) << Tokens; EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isPossibleMacro(Tokens[0])); EXPECT_TRUE(LeftRightQualifierAlignmentFixer::isPossibleMacro(Tokens[1])); diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 52a00c8a1a35da70b2962e8f71107c5f38d22040..3b36e407228195e447a67071dbd2d86c372875de 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -2287,6 +2287,51 @@ TEST_F(TokenAnnotatorTest, UnderstandTableGenTokens) { EXPECT_TOKEN(Tokens[0], tok::identifier, TT_TableGenBangOperator); Tokens = Annotate("!cond"); EXPECT_TOKEN(Tokens[0], tok::identifier, TT_TableGenCondOperator); + + auto AnnotateValue = [this, &Style](llvm::StringRef Code) { + // Values are annotated only in specific context. + auto Result = annotate(("def X { let V = " + Code + "; }").str(), Style); + return decltype(Result){Result.begin() + 6, Result.end() - 3}; + }; + // Both of bang/cond operators. + Tokens = AnnotateValue("!cond(!eq(x, 0): 1, true: x)"); + ASSERT_EQ(Tokens.size(), 15u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::identifier, TT_TableGenCondOperator); + EXPECT_TOKEN(Tokens[2], tok::identifier, TT_TableGenBangOperator); + EXPECT_TOKEN(Tokens[8], tok::colon, TT_TableGenCondOperatorColon); + EXPECT_TOKEN(Tokens[10], tok::comma, TT_TableGenCondOperatorComma); + EXPECT_TOKEN(Tokens[12], tok::colon, TT_TableGenCondOperatorColon); + // DAGArg values with operator identifier + Tokens = AnnotateValue("(ins type1:$src1, type2:$src2)"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_paren, TT_TableGenDAGArgOpener); + EXPECT_TOKEN(Tokens[3], tok::colon, TT_TableGenDAGArgListColon); + EXPECT_TOKEN(Tokens[4], tok::identifier, TT_Unknown); // $src1 + EXPECT_TOKEN(Tokens[5], tok::comma, TT_TableGenDAGArgListComma); + EXPECT_TOKEN(Tokens[7], tok::colon, TT_TableGenDAGArgListColon); + EXPECT_TOKEN(Tokens[9], tok::r_paren, TT_TableGenDAGArgCloser); + // List literal + Tokens = AnnotateValue("[1, 2, 3]"); + ASSERT_EQ(Tokens.size(), 7u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_square, TT_TableGenListOpener); + EXPECT_TOKEN(Tokens[6], tok::r_square, TT_TableGenListCloser); + // Suffixes of values + Tokens = AnnotateValue("valid.field"); + ASSERT_EQ(Tokens.size(), 3u) << Tokens; + EXPECT_TOKEN(Tokens[1], tok::period, TT_TableGenValueSuffix); + // Code + Tokens = AnnotateValue("[{ code is multiline string }]"); + ASSERT_EQ(Tokens.size(), 1u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::string_literal, TT_TableGenMultiLineString); + + // The definition + Tokens = annotate("def Def : Parent {}", Style); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; // This contains eof. + // We use inheritance colon and function brace. They are enough. + EXPECT_TOKEN(Tokens[2], tok::colon, TT_InheritanceColon); + EXPECT_TOKEN(Tokens[4], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_FunctionLBrace); } TEST_F(TokenAnnotatorTest, UnderstandConstructors) { diff --git a/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp b/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp index bc4eee73c1c2941de593e2c40b20a2805fa48452..59fef9ecbb9c916106bd6fbb278d634121c57c0b 100644 --- a/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp +++ b/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp @@ -583,7 +583,7 @@ TEST(MinimizeSourceToDependencyDirectivesTest, UnderscorePragma) { R"(_Pragma(u"clang module import"))", Out)); EXPECT_STREQ("\n", Out.data()); - // FIXME: R"()" strings depend on using C++ 11 language mode + // FIXME: R"()" strings depend on using C++11 language mode ASSERT_FALSE(minimizeSourceToDependencyDirectives( R"(_Pragma(R"abc(clang module import)abc"))", Out)); EXPECT_STREQ("\n", Out.data()); diff --git a/clang/unittests/Lex/PPCallbacksTest.cpp b/clang/unittests/Lex/PPCallbacksTest.cpp index e0a27b5111821b56d5ad971f60312437e8b33c2d..f3cdb1dfb28742fc92e0179eaa17118f15a7bdd0 100644 --- a/clang/unittests/Lex/PPCallbacksTest.cpp +++ b/clang/unittests/Lex/PPCallbacksTest.cpp @@ -37,7 +37,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, - StringRef RelativePath, const Module *Imported, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) override { this->HashLoc = HashLoc; this->IncludeTok = IncludeTok; @@ -47,7 +48,8 @@ public: this->File = File; this->SearchPath = SearchPath.str(); this->RelativePath = RelativePath.str(); - this->Imported = Imported; + this->SuggestedModule = SuggestedModule; + this->ModuleImported = ModuleImported; this->FileType = FileType; } @@ -59,7 +61,8 @@ public: OptionalFileEntryRef File; SmallString<16> SearchPath; SmallString<16> RelativePath; - const Module* Imported; + const Module *SuggestedModule; + bool ModuleImported; SrcMgr::CharacteristicKind FileType; }; diff --git a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp index dc10fa14c59598e5227157611de6daa8b3f7d3ff..48f55b8af97e4ee1d748b7106663f18949a53855 100644 --- a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp +++ b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp @@ -219,7 +219,7 @@ void EmitBuiltinDef(llvm::raw_ostream &OS, StringRef Substitution, break; } case BuiltinType::TargetBuiltin: - OS << ", \"\""; + OS << ", \"" << Builtin->getValueAsString("Features") << "\""; break; case BuiltinType::AtomicBuiltin: case BuiltinType::Builtin: diff --git a/clang/utils/TableGen/RISCVVEmitter.cpp b/clang/utils/TableGen/RISCVVEmitter.cpp index 9f6ed39f013092567831557a344debb10f67014f..8513174c88bfc3242635774806bc1fcc37293523 100644 --- a/clang/utils/TableGen/RISCVVEmitter.cpp +++ b/clang/utils/TableGen/RISCVVEmitter.cpp @@ -67,7 +67,9 @@ struct SemaRecord { bool HasMaskPolicy : 1; bool HasFRMRoundModeOp : 1; bool IsTuple : 1; + LLVM_PREFERRED_TYPE(PolicyScheme) uint8_t UnMaskedPolicyScheme : 2; + LLVM_PREFERRED_TYPE(PolicyScheme) uint8_t MaskedPolicyScheme : 2; }; diff --git a/clang/www/analyzer/alpha_checks.html b/clang/www/analyzer/alpha_checks.html index 11ef7d405dd4c817da6671c5df9a36d5be44085c..7bbe4a20288f23e0dd73125653971abb9f01825e 100644 --- a/clang/www/analyzer/alpha_checks.html +++ b/clang/www/analyzer/alpha_checks.html @@ -87,29 +87,6 @@ void test() { - - - -